blob: b88bf631c96f73e2c589f00aecb07f05ff3f937c [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 Krejci07d0fb92017-01-13 14:11:05 +0100193 default:
Radek Krejcifccd1442017-01-16 10:26:57 +0100194 LOGERR(LY_EINT, "parent type %d", elem_type);
Radek Krejcie534c132016-11-23 13:32:31 +0100195 return EXIT_FAILURE;
196 }
197
Radek Krejcifccd1442017-01-16 10:26:57 +0100198 if (type == LYEXT_SUBSTMT_SELF) {
199 /* parse for the statement self, not for the substatement */
200 child = yin;
201 next = NULL;
202 goto parseext;
203 }
204
Radek Krejci07d0fb92017-01-13 14:11:05 +0100205 LY_TREE_FOR_SAFE(yin->child, next, child) {
206 if (!strcmp(child->ns->value, LY_NSYIN)) {
207 /* skip the regular YIN nodes */
208 continue;
209 }
210
211 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100212parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100213
214 /* first, allocate a space for the extension instance in the parent elem */
215 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
216 if (!reallocated) {
217 LOGMEM;
218 return EXIT_FAILURE;
219 }
220 (*ext) = reallocated;
221
222 /* init memory */
223 (*ext)[(*ext_size)] = NULL;
224
225 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100226 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100227 (*ext_size)++;
228 if (r) {
229 return EXIT_FAILURE;
230 }
231
Radek Krejcifccd1442017-01-16 10:26:57 +0100232 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100233 }
234
Radek Krejcie534c132016-11-23 13:32:31 +0100235 return EXIT_SUCCESS;
236}
237
Michal Vasko0d343d12015-08-24 14:57:36 +0200238/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200239static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200240fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
241 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100242{
Radek Krejci5323b492017-01-16 15:40:11 +0100243 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100244 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100245 struct lyxml_elem *node, *next;
Michal Vasko1d337e12016-02-15 12:32:04 +0100246
247 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200248
249 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
250 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200251error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100252 return EXIT_FAILURE;
253 }
254
Michal Vasko56d082c2016-10-25 14:00:42 +0200255 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100256 return EXIT_FAILURE;
257 }
258
Radek Krejci9de2c042016-10-19 16:53:06 +0200259 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100260 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200261 if (r) {
262 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100263 }
264
Radek Krejci5323b492017-01-16 15:40:11 +0100265 LY_TREE_FOR_SAFE(yin->child, next, node) {
266 if (!node->ns) {
267 /* garbage */
268 lyxml_free(parent->module->ctx, node);
269 } else if (strcmp(node->ns->value, LY_NSYIN)) {
270 /* extension */
271 c_ext++;
272 } else {
273 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
274 return EXIT_FAILURE;
275 }
276 }
277 if (c_ext) {
278 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
279 if (!iffeat->ext) {
280 LOGMEM;
281 return EXIT_FAILURE;
282 }
283 LY_TREE_FOR_SAFE(yin->child, next, node) {
284 /* extensions */
285 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100286 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100287 iffeat->ext_size++;
288 if (r) {
289 return EXIT_FAILURE;
290 }
291 }
292 }
293
Radek Krejci9ff0a922016-07-14 13:08:05 +0200294 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100295}
296
297/* logs directly */
298static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200299fill_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 +0200300{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200301 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200302 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200303 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100304 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100305 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200306
Michal Vasko4cfcd252015-08-03 14:31:10 +0200307 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100308 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200309
Radek Krejci07d0fb92017-01-13 14:11:05 +0100310 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100311 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200312 }
Radek Krejci04581c62015-05-22 21:24:00 +0200313
Pavol Vicand6cda452016-07-13 15:08:29 +0200314 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100315 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200316 }
317
Radek Krejcie534c132016-11-23 13:32:31 +0100318 LY_TREE_FOR(yin->child, node) {
319 if (strcmp(node->ns->value, LY_NSYIN)) {
320 /* extension */
321 c_ext++;
322 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200323 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100324 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100325 goto error;
326 }
327 if (read_yin_subnode_ext(module, ident, LYEXT_PAR_IDENT, node, LYEXT_SUBSTMT_BASE, c_base, unres)) {
328 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200329 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200330 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100331
Radek Krejci018f1f52016-08-03 16:01:20 +0200332 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
333 c_ftrs++;
334
335 } else {
336 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100337 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200338 }
339 }
340
341 if (c_base) {
342 ident->base_size = 0;
343 ident->base = calloc(c_base, sizeof *ident->base);
344 if (!ident->base) {
345 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100346 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200347 }
348 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200349 if (c_ftrs) {
350 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
351 if (!ident->iffeature) {
352 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100353 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200354 }
355 }
Radek Krejcie534c132016-11-23 13:32:31 +0100356 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100357 /* some extensions may be already present from the substatements */
358 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
359 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +0100360 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100361 goto error;
Radek Krejcie534c132016-11-23 13:32:31 +0100362 }
Radek Krejci18a44882017-01-23 13:47:29 +0100363 ident->ext = reallocated;
364
365 /* init memory */
366 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100367 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200368
Radek Krejcie534c132016-11-23 13:32:31 +0100369 LY_TREE_FOR_SAFE(yin->child, next, node) {
370 if (strcmp(node->ns->value, LY_NSYIN)) {
371 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100372 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 +0100373 ident->ext_size++;
374 if (rc) {
375 goto error;
376 }
377 } else if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200378 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100379 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100380 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100381 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200382 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100383
Radek Krejci48464ed2016-03-17 15:44:09 +0100384 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100385 lydict_remove(module->ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100386 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100387 }
388 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200389 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200390 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200391 ident->iffeature_size++;
392 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100393 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200394 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 }
Radek Krejci04581c62015-05-22 21:24:00 +0200397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200398 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200399
400error:
401 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200402}
403
Michal Vasko0d343d12015-08-24 14:57:36 +0200404/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200405static int
Radek Krejcifccd1442017-01-16 10:26:57 +0100406read_restr_substmt(struct lys_module *module, LYEXT_PAR restr_type, struct lys_restr *restr, struct lyxml_elem *yin,
407 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200408{
Radek Krejcifccd1442017-01-16 10:26:57 +0100409 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200410 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200411
Radek Krejcifccd1442017-01-16 10:26:57 +0100412 LY_TREE_FOR_SAFE(yin->child, next, child) {
413 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200414 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200415 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100416 } else if (strcmp(child->ns->value, LY_NSYIN)) {
417 /* extension */
Radek Krejciac00b2a2017-01-17 14:05:00 +0100418 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100419 return EXIT_FAILURE;
420 }
421 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200422 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100423 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200424 return EXIT_FAILURE;
425 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100426 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100427 return EXIT_FAILURE;
428 }
429 restr->dsc = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200430 if (!restr->dsc) {
431 return EXIT_FAILURE;
432 }
433 } else if (!strcmp(child->name, "reference")) {
434 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100435 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200436 return EXIT_FAILURE;
437 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100438 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100439 return EXIT_FAILURE;
440 }
441 restr->ref = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200442 if (!restr->ref) {
443 return EXIT_FAILURE;
444 }
445 } else if (!strcmp(child->name, "error-app-tag")) {
446 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200448 return EXIT_FAILURE;
449 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100450 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100451 return EXIT_FAILURE;
452 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200453 GETVAL(value, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +0100454 restr->eapptag = lydict_insert(module->ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200455 } else if (!strcmp(child->name, "error-message")) {
456 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100457 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200458 return EXIT_FAILURE;
459 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100460 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100461 return EXIT_FAILURE;
462 }
463 restr->emsg = read_yin_subnode(module->ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200464 if (!restr->emsg) {
465 return EXIT_FAILURE;
466 }
467 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100468 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200469 return EXIT_FAILURE;
470 }
Radek Krejci41726f92015-06-19 13:11:05 +0200471 }
472
473 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200474
475error:
476 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200477}
478
Michal Vasko88c29542015-11-27 14:57:53 +0100479/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
480int
Radek Krejcib8048692015-08-05 13:36:34 +0200481fill_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 +0200482 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200483{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200484 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200485 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100486 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100487 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200488 struct lys_type_bit bit, *bits_sc = NULL;
489 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200490 struct lys_type *dertype;
Radek Krejcie534c132016-11-23 13:32:31 +0100491 int i, j, rc, val_set, c_ftrs, c_ext = 0;
Radek Krejcidc008d72016-02-17 13:12:14 +0100492 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200493 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200494 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200495 size_t len;
496 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200497
Radek Krejcie534c132016-11-23 13:32:31 +0100498 /* init */
499 memset(&exts, 0, sizeof exts);
500
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200501 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100502 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200503 if (!value) {
504 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200505 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200506
507 i = parse_identifier(value);
508 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100509 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100510 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200511 goto error;
512 }
513 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100514 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200515 if (value[i]) {
516 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100517 name += i;
518 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100519 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100520 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200521 goto error;
522 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200523 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100524 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200525 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200526
Radek Krejci225376f2016-02-16 17:36:22 +0100527 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200528 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100529 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200530 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200531 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100532
533 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200534 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200535 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200536 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100537 ret = EXIT_FAILURE;
538 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200539 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200540 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200541
Radek Krejci9b6aad22016-09-20 15:55:51 +0200542 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200543 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200544 * 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 +0200545 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
546 if (siter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +0100547#if __BYTE_ORDER == __LITTLE_ENDIAN
548 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]) {
Radek Krejcic13db382016-08-16 10:52:42 +0200549 LOGINT;
550 goto error;
551 }
Radek Krejci6ff885d2017-01-03 14:06:22 +0100552 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]--;
553#else
554 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]) {
555 LOGINT;
556 goto error;
557 }
558 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]--;
559#endif
Radek Krejcic13db382016-08-16 10:52:42 +0200560 } else {
561 LOGINT;
562 goto error;
563 }
564 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200565 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200566
Radek Krejcicf509982015-12-15 09:22:44 +0100567 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100568 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100569 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100570 return -1;
571 }
572
Radek Krejcie534c132016-11-23 13:32:31 +0100573 /* parse extension instances */
574 LY_TREE_FOR_SAFE(yin->child, next, node) {
575 if (!node->ns) {
576 /* garbage */
577 lyxml_free(module->ctx, node);
578 continue;
579 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
580 /* YANG (YIN) statements - process later */
581 continue;
582 }
583
584 lyxml_unlink_elem(module->ctx, node, 2);
585 lyxml_add_child(module->ctx, &exts, node);
586 c_ext++;
587 }
588 if (c_ext) {
589 type->ext = calloc(c_ext, sizeof *type->ext);
590 if (!type->ext) {
591 LOGMEM;
592 goto error;
593 }
594 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100595 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 +0100596 type->ext_size++;
597 if (rc) {
598 goto error;
599 }
600 }
601 }
602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200603 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200604 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200605 /* RFC 6020 9.7.4 - bit */
606
607 /* get bit specifications, at least one must be present */
608 LY_TREE_FOR_SAFE(yin->child, next, node) {
609 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200610 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200611 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100612 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200613 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200614 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200615 }
616 }
Radek Krejcie663e012016-08-01 17:12:34 +0200617 dertype = &type->der->type;
618 if (!dertype->der) {
619 if (!type->info.bits.count) {
620 /* type is derived directly from buit-in bits type and bit statement is required */
621 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
622 goto error;
623 }
624 } else {
625 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
626 if (module->version < 2 && type->info.bits.count) {
627 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
628 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
629 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200630 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200631 goto error;
632 }
Radek Krejciac781922015-07-09 15:35:14 +0200633 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200634
635 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100636 if (!type->info.bits.bit) {
637 LOGMEM;
638 goto error;
639 }
Radek Krejci73adb602015-07-02 18:07:40 +0200640 p = 0;
641 i = -1;
642 LY_TREE_FOR(yin->child, next) {
643 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200644 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200645
646 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100647 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100648 goto error;
649 }
650
Radek Krejci994b6f62015-06-18 16:47:27 +0200651 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100652 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 +0200653 type->info.bits.count = i + 1;
654 goto error;
655 }
656
Radek Krejcie663e012016-08-01 17:12:34 +0200657 if (!dertype->der) { /* directly derived type from bits built-in type */
658 /* check the name uniqueness */
659 for (j = 0; j < i; j++) {
660 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
661 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
662 type->info.bits.count = i + 1;
663 goto error;
664 }
665 }
666 } else {
667 /* restricted bits type - the name MUST be used in the base type */
668 bits_sc = dertype->info.bits.bit;
669 for (j = 0; j < dertype->info.bits.count; j++) {
670 if (ly_strequal(bits_sc[j].name, value, 1)) {
671 break;
672 }
673 }
674 if (j == dertype->info.bits.count) {
675 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200676 type->info.bits.count = i + 1;
677 goto error;
678 }
679 }
680
Radek Krejcie663e012016-08-01 17:12:34 +0200681
Radek Krejci0d70c372015-07-02 16:23:10 +0200682 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100683 LY_TREE_FOR_SAFE(next->child, next2, node) {
684 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200685 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200686 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100687 } else if (strcmp(node->ns->value, LY_NSYIN)) {
688 /* extension */
689 if (read_yin_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
690 LYEXT_SUBSTMT_SELF, 0, unres)) {
691 goto error;
692 }
693 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200694 if (p_ != -1) {
695 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
696 type->info.bits.count = i + 1;
697 goto error;
698 }
699
Radek Krejci0d70c372015-07-02 16:23:10 +0200700 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200701 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200702
703 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200704 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100705 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200706 type->info.bits.count = i + 1;
707 goto error;
708 }
709 type->info.bits.bit[i].pos = (uint32_t)p_;
710
Radek Krejcie663e012016-08-01 17:12:34 +0200711 if (!dertype->der) { /* directly derived type from bits built-in type */
712 /* keep the highest enum value for automatic increment */
713 if (type->info.bits.bit[i].pos >= p) {
714 p = type->info.bits.bit[i].pos;
715 p++;
716 } else {
717 /* check that the value is unique */
718 for (j = 0; j < i; j++) {
719 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
720 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
721 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
722 type->info.bits.bit[j].name);
723 type->info.bits.count = i + 1;
724 goto error;
725 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200726 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200727 }
728 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200729
Radek Krejci9b15fea2017-01-23 11:31:43 +0100730 if (read_yin_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
731 LYEXT_SUBSTMT_POSITION, 0, unres)) {
732 goto error;
733 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200734 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
735 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200736 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100737 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200738 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200739 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200740 }
Radek Krejcie663e012016-08-01 17:12:34 +0200741
742 if (!dertype->der) { /* directly derived type from bits built-in type */
743 if (p_ == -1) {
744 /* assign value automatically */
745 if (p > UINT32_MAX) {
746 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
747 type->info.bits.count = i + 1;
748 goto error;
749 }
750 type->info.bits.bit[i].pos = (uint32_t)p;
751 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
752 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200753 }
Radek Krejcie663e012016-08-01 17:12:34 +0200754 } else { /* restricted bits type */
755 if (p_ == -1) {
756 /* automatically assign position from base type */
757 type->info.bits.bit[i].pos = bits_sc[j].pos;
758 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
759 } else {
760 /* check that the assigned position corresponds to the original
761 * position of the bit in the base type */
762 if (p_ != bits_sc[j].pos) {
763 /* p_ - assigned position in restricted bits
764 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
765 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200766 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200767 type->info.bits.count = i + 1;
768 goto error;
769 }
770 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200771 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200772
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200773 /* if-features */
774 if (c_ftrs) {
775 bits_sc = &type->info.bits.bit[i];
776 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
777 if (!bits_sc->iffeature) {
778 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200779 type->info.bits.count = i + 1;
780 goto error;
781 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200782
783 LY_TREE_FOR(next->child, node) {
784 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200785 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200786 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
787 bits_sc->iffeature_size++;
788 if (rc) {
789 type->info.bits.count = i + 1;
790 goto error;
791 }
792 }
793 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200794 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200795
796 /* keep them ordered by position */
797 j = i;
798 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
799 /* switch them */
800 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
801 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
802 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
803 j--;
804 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200805 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200806 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200808 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200809 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200810 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200811
Radek Krejcif9401c32015-06-26 16:47:36 +0200812 if (!strcmp(node->name, "range")) {
813 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100814 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200815 goto error;
816 }
817
818 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200819 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100820 if (!type->info.dec64.range) {
821 LOGMEM;
822 goto error;
823 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200824 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
825
826 /* get possible substatements */
Radek Krejcifdc0d702017-01-23 15:58:38 +0100827 if (read_restr_substmt(module, LYEXT_PAR_RESTR, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200828 goto error;
829 }
830 } else if (!strcmp(node->name, "fraction-digits")) {
831 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100832 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200833 goto error;
834 }
835 GETVAL(value, node, "value");
836 v = strtol(value, NULL, 10);
837
838 /* range check */
839 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100840 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200841 goto error;
842 }
843 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200844 type->info.dec64.div = 10;
845 for (i = 1; i < v; i++) {
846 type->info.dec64.div *= 10;
847 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100848
849 /* extensions */
850 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
851 goto error;
852 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200853 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100854 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200855 goto error;
856 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200857 }
858
859 /* mandatory sub-statement(s) check */
860 if (!type->info.dec64.dig && !type->der->type.der) {
861 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100862 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200863 goto error;
864 }
Radek Krejci7511f402015-07-10 09:56:30 +0200865 if (type->info.dec64.dig && type->der->type.der) {
866 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100867 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200868 goto error;
869 }
Radek Krejci4800f652016-09-08 14:02:52 +0200870
871 /* copy fraction-digits specification from parent type for easier internal use */
872 if (type->der->type.der) {
873 type->info.dec64.dig = type->der->type.info.dec64.dig;
874 type->info.dec64.div = type->der->type.info.dec64.div;
875 }
876
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200877 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
878 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
879 goto error;
880 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200884 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200885
Radek Krejci994b6f62015-06-18 16:47:27 +0200886 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200889 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200890 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200891 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100892 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200893 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200894 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 }
896 }
Radek Krejcie663e012016-08-01 17:12:34 +0200897 dertype = &type->der->type;
898 if (!dertype->der) {
899 if (!type->info.enums.count) {
900 /* type is derived directly from buit-in enumeartion type and enum statement is required */
901 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
902 goto error;
903 }
904 } else {
905 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
906 if (module->version < 2 && type->info.enums.count) {
907 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
908 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
909 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200910 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200911 goto error;
912 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200913 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200914
Radek Krejci1574a8d2015-08-03 14:16:52 +0200915 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100916 if (!type->info.enums.enm) {
917 LOGMEM;
918 goto error;
919 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200920
Radek Krejcie663e012016-08-01 17:12:34 +0200921 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200922 i = -1;
923 LY_TREE_FOR(yin->child, next) {
924 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200925 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200926
927 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100928 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100929 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
930 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100931 goto error;
932 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200933 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100934 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 +0200935 type->info.enums.count = i + 1;
936 goto error;
937 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200940 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100942 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 type->info.enums.count = i + 1;
944 goto error;
945 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200946
Radek Krejcie663e012016-08-01 17:12:34 +0200947 if (!dertype->der) { /* directly derived type from enumeration built-in type */
948 /* check the name uniqueness */
949 for (j = 0; j < i; j++) {
950 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
951 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
952 type->info.enums.count = i + 1;
953 goto error;
954 }
955 }
956 } else {
957 /* restricted enumeration type - the name MUST be used in the base type */
958 enms_sc = dertype->info.enums.enm;
959 for (j = 0; j < dertype->info.enums.count; j++) {
960 if (ly_strequal(enms_sc[j].name, value, 1)) {
961 break;
962 }
963 }
964 if (j == dertype->info.enums.count) {
965 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200966 type->info.enums.count = i + 1;
967 goto error;
968 }
969 }
Radek Krejci04581c62015-05-22 21:24:00 +0200970
Radek Krejcie663e012016-08-01 17:12:34 +0200971 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100972 LY_TREE_FOR_SAFE(next->child, next2, node) {
973 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200974 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200975 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100976 } else if (strcmp(node->ns->value, LY_NSYIN)) {
977 /* extensions */
978 if (read_yin_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
979 LYEXT_SUBSTMT_SELF, 0, unres)) {
980 goto error;
981 }
982 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200983 if (val_set) {
984 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
985 type->info.enums.count = i + 1;
986 goto error;
987 }
988
Radek Krejci0d70c372015-07-02 16:23:10 +0200989 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200990 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200991
992 /* range check */
993 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100994 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200995 type->info.enums.count = i + 1;
996 goto error;
997 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200998 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200999
Radek Krejcie663e012016-08-01 17:12:34 +02001000 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001001 if (!i) {
1002 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001003 v = type->info.enums.enm[i].value;
1004 v++;
1005 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001006 /* keep the highest enum value for automatic increment */
1007 if (type->info.enums.enm[i].value >= v) {
1008 v = type->info.enums.enm[i].value;
1009 v++;
1010 } else {
1011 /* check that the value is unique */
1012 for (j = 0; j < i; j++) {
1013 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
1014 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
1015 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1016 type->info.enums.enm[j].name);
1017 type->info.enums.count = i + 1;
1018 goto error;
1019 }
Radek Krejcie663e012016-08-01 17:12:34 +02001020 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001021 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 }
1023 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001024 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001025
Radek Krejci9b15fea2017-01-23 11:31:43 +01001026 if (read_yin_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
1027 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1028 goto error;
1029 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001030 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
1031 c_ftrs++;
1032
Radek Krejci0d70c372015-07-02 16:23:10 +02001033 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001034 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001035 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001037 }
Radek Krejcie663e012016-08-01 17:12:34 +02001038
1039 if (!dertype->der) { /* directly derived type from enumeration */
1040 if (!val_set) {
1041 /* assign value automatically */
1042 if (v > INT32_MAX) {
1043 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1044 type->info.enums.count = i + 1;
1045 goto error;
1046 }
1047 type->info.enums.enm[i].value = v;
1048 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1049 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 }
Radek Krejcie663e012016-08-01 17:12:34 +02001051 } else { /* restricted enum type */
1052 if (!val_set) {
1053 /* automatically assign value from base type */
1054 type->info.enums.enm[i].value = enms_sc[j].value;
1055 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1056 } else {
1057 /* check that the assigned value corresponds to the original
1058 * value of the enum in the base type */
1059 if (v_ != enms_sc[j].value) {
1060 /* v_ - assigned value in restricted enum
1061 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1062 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001063 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001064 type->info.enums.count = i + 1;
1065 goto error;
1066 }
1067 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001068 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001069
1070 /* if-features */
1071 if (c_ftrs) {
1072 enms_sc = &type->info.enums.enm[i];
1073 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1074 if (!enms_sc->iffeature) {
1075 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076 type->info.enums.count = i + 1;
1077 goto error;
1078 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001079
1080 LY_TREE_FOR(next->child, node) {
1081 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001082 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001083 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1084 enms_sc->iffeature_size++;
1085 if (rc) {
1086 type->info.enums.count = i + 1;
1087 goto error;
1088 }
1089 }
1090 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001091 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 }
1094 break;
1095
1096 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001097 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098
Michal Vaskof2d43962016-09-02 11:10:16 +02001099 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001100 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001101
Michal Vaskoe29c6622015-11-27 15:02:31 +01001102 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001103 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001104 goto error;
1105 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001106
1107 GETVAL(value, yin->child, "name");
1108 /* store in the JSON format */
1109 value = transform_schema2json(module, value);
1110 if (!value) {
1111 goto error;
1112 }
1113 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
1114 lydict_remove(module->ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001115 if (rc == -1) {
1116 goto error;
1117 }
Radek Krejci18a44882017-01-23 13:47:29 +01001118
1119 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
1120 goto error;
1121 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001122 }
1123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001125 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001126 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001127 break;
1128 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001129 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001130 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001131 } else {
1132 if (type->der->type.der) {
1133 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1134 goto error;
1135 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001138 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139 goto error;
1140 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141 break;
1142
1143 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001144 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001145 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001146
Radek Krejciaf351422015-06-19 14:49:38 +02001147 if (!strcmp(node->name, "require-instance")) {
1148 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001149 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001150 goto error;
1151 }
1152 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001153 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001154 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001155 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001156 type->info.inst.req = -1;
1157 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001158 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001159 goto error;
1160 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001161
1162 /* extensions */
1163 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINST, 0, unres)) {
1164 goto error;
1165 }
Radek Krejciaf351422015-06-19 14:49:38 +02001166 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001167 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001168 goto error;
1169 }
Radek Krejciaf351422015-06-19 14:49:38 +02001170 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 break;
1173
Radek Krejcif2860132015-06-20 12:37:20 +02001174 case LY_TYPE_BINARY:
1175 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001176 case LY_TYPE_INT8:
1177 case LY_TYPE_INT16:
1178 case LY_TYPE_INT32:
1179 case LY_TYPE_INT64:
1180 case LY_TYPE_UINT8:
1181 case LY_TYPE_UINT16:
1182 case LY_TYPE_UINT32:
1183 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001184 /* RFC 6020 9.2.4 - range */
1185
1186 /* length and range are actually the same restriction, so process
1187 * them by this common code, we just need to differ the name and
1188 * structure where the information will be stored
1189 */
1190 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001191 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001192 name = "length";
1193 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001194 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001195 name = "range";
1196 }
1197
Radek Krejci73adb602015-07-02 18:07:40 +02001198 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001199
Radek Krejcif2860132015-06-20 12:37:20 +02001200 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001201 if (*restrs) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001202 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001203 goto error;
1204 }
1205
1206 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001207 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001208 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001209 goto error;
1210 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001211 *restrs = calloc(1, sizeof **restrs);
1212 if (!(*restrs)) {
Michal Vasko253035f2015-12-17 16:58:13 +01001213 LOGMEM;
1214 goto error;
1215 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001216 (*restrs)->expr = lydict_insert(module->ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001217
1218 /* get possible substatements */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001219 if (read_restr_substmt(module, LYEXT_PAR_RESTR, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001220 goto error;
1221 }
1222 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001223 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001224 goto error;
1225 }
Radek Krejcif2860132015-06-20 12:37:20 +02001226 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001227 break;
1228
1229 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001230 /* flag resolving for later use */
1231 if (!tpdftype) {
1232 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1233 if (siter) {
1234 /* just a flag - do not resolve */
1235 tpdftype = 1;
1236 }
1237 }
1238
Radek Krejcidc4c1412015-06-19 15:39:54 +02001239 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001240 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001241
Michal Vasko88c29542015-11-27 14:57:53 +01001242 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001243 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001244 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001245 goto error;
1246 }
1247
1248 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001249 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001250 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001251 if (!type->info.lref.path) {
1252 goto error;
1253 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001254
1255 /* try to resolve leafref path only when this is instantiated
1256 * leaf, so it is not:
1257 * - typedef's type,
1258 * - in grouping definition,
1259 * - just instantiated in a grouping definition,
1260 * because in those cases the nodes referenced in path might not be present
1261 * and it is not a bug. */
1262 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001263 goto error;
1264 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001265
1266 /* extensions */
1267 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
1268 goto error;
1269 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001270 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001271 if (type->info.lref.req) {
1272 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1273 goto error;
1274 }
1275 GETVAL(value, node, "value");
1276 if (!strcmp(value, "true")) {
1277 type->info.lref.req = 1;
1278 } else if (!strcmp(value, "false")) {
1279 type->info.lref.req = -1;
1280 } else {
1281 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1282 goto error;
1283 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001284
1285 /* extensions */
1286 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINST, 0, unres)) {
1287 goto error;
1288 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001289 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001290 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001291 goto error;
1292 }
Radek Krejci73adb602015-07-02 18:07:40 +02001293 }
1294
Radek Krejci742be352016-07-17 12:18:54 +02001295 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001296 if (!type->der->type.der) {
1297 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1298 goto error;
1299 } else {
1300 /* copy leafref definition into the derived type */
1301 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1302 /* and resolve the path at the place we are (if not in grouping/typedef) */
1303 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1304 goto error;
1305 }
1306
1307 /* add pointer to leafref target, only on leaves (not in typedefs) */
1308 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1309 goto error;
1310 }
1311 }
Radek Krejci742be352016-07-17 12:18:54 +02001312 }
1313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001314 break;
1315
1316 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001317 /* RFC 6020 9.4.4 - length */
1318 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001319 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001320 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001321
Radek Krejci3733a802015-06-19 13:43:21 +02001322 if (!strcmp(node->name, "length")) {
1323 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001324 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001325 goto error;
1326 }
1327
1328 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001329 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001330 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001331 goto error;
1332 }
1333 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001334 if (!type->info.str.length) {
1335 LOGMEM;
1336 goto error;
1337 }
Radek Krejci3733a802015-06-19 13:43:21 +02001338 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1339
Radek Krejci5fbc9162015-06-19 14:11:11 +02001340 /* get possible sub-statements */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001341 if (read_restr_substmt(module, LYEXT_PAR_RESTR, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001342 goto error;
1343 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001344 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001345 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001346 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001347 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001348 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001349 goto error;
1350 }
1351 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001352 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001353 if (i) {
1354 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001355 if (!type->info.str.patterns) {
1356 LOGMEM;
1357 goto error;
1358 }
Radek Krejci73adb602015-07-02 18:07:40 +02001359 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001360 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001361 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001362 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001363 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001364 goto error;
1365 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001366 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Michal Vasko69068852015-07-13 14:34:31 +02001367
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001368 modifier = 0x06; /* ACK */
1369 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001370 if (module->version >= 2) {
1371 LY_TREE_FOR_SAFE(node->child, next2, child) {
1372 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1373 if (name) {
1374 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1375 goto error;
1376 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001377
Radek Krejcifccd1442017-01-16 10:26:57 +01001378 GETVAL(name, child, "value");
1379 if (!strcmp(name, "invert-match")) {
1380 modifier = 0x15; /* NACK */
1381 } else {
1382 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1383 goto error;
1384 }
1385 /* get extensions of the modifier */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001386 if (read_yin_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciac00b2a2017-01-17 14:05:00 +01001387 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001388 return EXIT_FAILURE;
1389 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001390
Radek Krejcifccd1442017-01-16 10:26:57 +01001391 lyxml_free(module->ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001392 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001393 }
1394 }
1395
1396 len = strlen(value);
1397 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1398 buf[0] = modifier;
1399 strcpy(&buf[1], value);
1400
Radek Krejcifccd1442017-01-16 10:26:57 +01001401 restr->expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001402
1403 /* get possible sub-statements */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001404 if (read_restr_substmt(module, LYEXT_PAR_RESTR, restr, node, unres)) {
Michal Vasko69068852015-07-13 14:34:31 +02001405 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001406 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001407 goto error;
1408 }
Radek Krejci73adb602015-07-02 18:07:40 +02001409 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001410 }
1411 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001412 break;
1413
1414 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001415 /* RFC 6020 7.4 - type */
1416 /* count number of types in union */
1417 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001418 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001419
Radek Krejcie4c366b2015-07-02 10:11:31 +02001420 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001421 if (type->der->type.der) {
1422 /* type can be a substatement only in "union" type, not in derived types */
1423 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1424 goto error;
1425 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001426 i++;
1427 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001428 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001429 goto error;
1430 }
1431 }
1432
Radek Krejci038d5d92016-09-12 15:07:15 +02001433 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001434 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001435 goto error;
1436 }
1437
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001438 /* inherit instid presence information */
1439 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1440 type->info.uni.has_ptr_type = 1;
1441 }
1442
Radek Krejcie4c366b2015-07-02 10:11:31 +02001443 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001444 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001445 if (!type->info.uni.types) {
1446 LOGMEM;
1447 goto error;
1448 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001449 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001450 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001451 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001452 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001453 if (!rc) {
1454 type->info.uni.count++;
1455
Radek Krejci7de36cf2016-09-12 16:18:50 +02001456 if (module->version < 2) {
1457 /* union's type cannot be empty or leafref */
1458 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1459 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1460 rc = -1;
1461 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1462 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1463 rc = -1;
1464 }
Michal Vasko88c29542015-11-27 14:57:53 +01001465 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001466
1467 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1468 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1469 type->info.uni.has_ptr_type = 1;
1470 }
Michal Vasko88c29542015-11-27 14:57:53 +01001471 }
1472 if (rc) {
1473 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1474 for (i = 0; i < type->info.uni.count; ++i) {
1475 lys_type_free(module->ctx, &type->info.uni.types[i]);
1476 }
1477 free(type->info.uni.types);
1478 type->info.uni.types = NULL;
1479 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001480 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001481 type->der = NULL;
1482 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001483
1484 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001485 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001486 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001487 goto error;
1488 }
Michal Vasko88c29542015-11-27 14:57:53 +01001489 }
1490 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001491
Michal Vasko88c29542015-11-27 14:57:53 +01001492 case LY_TYPE_BOOL:
1493 case LY_TYPE_EMPTY:
1494 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001495 if (yin->child) {
1496 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
1497 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001498 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001499 break;
1500
1501 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001502 LOGINT;
1503 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001504 }
1505
1506 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001507
1508error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001509 if (type->module_name) {
1510 lydict_remove(module->ctx, type->module_name);
1511 type->module_name = NULL;
1512 }
Radek Krejcie534c132016-11-23 13:32:31 +01001513 lyxml_free_withsiblings(module->ctx, exts.child);
1514
Radek Krejcidc008d72016-02-17 13:12:14 +01001515 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001516}
1517
Michal Vasko0d343d12015-08-24 14:57:36 +02001518/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001520fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1521 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001522{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001524 struct lyxml_elem *node, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001525 int rc, has_type = 0, c_ext = 0;
Radek Krejci59a349f2017-01-24 10:14:31 +01001526 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001528 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001529 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 goto error;
1531 }
1532 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001535 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001536 goto error;
1537 }
Radek Krejcieac35532015-05-31 19:09:15 +02001538
Michal Vasko88c29542015-11-27 14:57:53 +01001539 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001540 if (strcmp(node->ns->value, LY_NSYIN)) {
1541 /* extension */
1542 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001543 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001544 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001545 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001546 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001547 goto error;
1548 }
Michal Vasko88c29542015-11-27 14:57:53 +01001549 /* HACK for unres */
1550 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001551 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001552 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001553 goto error;
1554 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001555 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001556
Radek Krejci07d0fb92017-01-13 14:11:05 +01001557 /* 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 +01001558 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 } else if (!strcmp(node->name, "default")) {
1560 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001561 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001562 goto error;
1563 }
1564 GETVAL(value, node, "value");
1565 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001566
1567 if (read_yin_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
1568 goto error;
1569 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 } else if (!strcmp(node->name, "units")) {
1571 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001572 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 goto error;
1574 }
1575 GETVAL(value, node, "name");
1576 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001577
1578 if (read_yin_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
1579 goto error;
1580 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001582 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001583 goto error;
1584 }
Radek Krejcie534c132016-11-23 13:32:31 +01001585
1586 lyxml_free(module->ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001589 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001590 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001591 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 goto error;
1593 }
Radek Krejcieac35532015-05-31 19:09:15 +02001594
Michal Vasko478c4652016-07-21 12:55:01 +02001595 /* check default value (if not defined, there still could be some restrictions
1596 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01001597 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 +02001598 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001599 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001600
Radek Krejcie534c132016-11-23 13:32:31 +01001601 /* finish extensions parsing */
1602 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001603 /* some extensions may be already present from the substatements */
1604 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
1605 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001606 LOGMEM;
1607 goto error;
1608 }
Radek Krejci59a349f2017-01-24 10:14:31 +01001609 tpdf->ext = reallocated;
1610
1611 /* init memory */
1612 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1613
Radek Krejcie534c132016-11-23 13:32:31 +01001614 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001615 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 +01001616 tpdf->ext_size++;
1617 if (rc) {
1618 goto error;
1619 }
1620 }
1621 }
1622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001624
1625error:
1626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001628}
1629
Radek Krejcia1a6b762016-11-14 09:53:38 +09001630static int
Radek Krejcie534c132016-11-23 13:32:31 +01001631fill_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 +09001632{
1633 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001634 struct lyxml_elem *child, *node, *next, *next2;
1635 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001636 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001637
1638 GETVAL(value, yin, "name");
1639
1640 if (lyp_check_identifier(value, LY_IDENT_EXTENSION, module, NULL)) {
1641 goto error;
1642 }
1643 ext->name = lydict_insert(module->ctx, value, strlen(value));
1644
Radek Krejci07d0fb92017-01-13 14:11:05 +01001645 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001646 goto error;
1647 }
1648
Radek Krejcie534c132016-11-23 13:32:31 +01001649 LY_TREE_FOR_SAFE(yin->child, next, node) {
1650 if (strcmp(node->ns->value, LY_NSYIN)) {
1651 /* possible extension instance */
1652 c_ext++;
1653 } else if (!strcmp(node->name, "argument")) {
1654 /* argument */
1655 GETVAL(value, node, "name");
1656 ext->argument = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1fb02182017-01-24 11:20:55 +01001657 if (read_yin_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
1658 goto error;
1659 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001660
Radek Krejcia1a6b762016-11-14 09:53:38 +09001661 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001662 LY_TREE_FOR_SAFE(node->child, next2, child) {
1663 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
1664 GETVAL(value, child, "value");
1665 if (ly_strequal(value, "true", 0)) {
1666 ext->flags |= LYS_YINELEM;
1667 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001668
1669 if (read_yin_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
1670 goto error;
1671 }
Radek Krejcie534c132016-11-23 13:32:31 +01001672 } else if (child->ns) {
1673 /* unexpected YANG statement */
1674 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
1675 goto error;
1676 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001677 }
1678
Radek Krejcie534c132016-11-23 13:32:31 +01001679 lyxml_free(module->ctx, node);
1680 } else {
1681 /* unexpected YANG statement */
1682 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
1683 goto error;
1684 }
1685 }
1686
1687 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001688 /* some extensions may be already present from the substatements */
1689 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
1690 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001691 LOGMEM;
1692 goto error;
1693 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001694 ext->ext = reallocated;
1695
1696 /* init memory */
1697 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1698
1699 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001700 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001701 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 +01001702 ext->ext_size++;
1703 if (rc) {
1704 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001705 }
1706 }
1707 }
1708
Radek Krejci0a498f82017-01-04 16:24:15 +01001709 /* search for plugin */
1710 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 +09001711
1712 return EXIT_SUCCESS;
1713
1714error:
1715 return EXIT_FAILURE;
1716}
1717
Michal Vasko0d343d12015-08-24 14:57:36 +02001718/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001719static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001720fill_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 +02001721{
1722 const char *value;
1723 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001724 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001725 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001726
Radek Krejcib05774c2015-06-18 13:52:59 +02001727 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001728 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001729 goto error;
1730 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001731 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001732 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001733
Radek Krejci07d0fb92017-01-13 14:11:05 +01001734 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001735 goto error;
1736 }
1737
Radek Krejcie534c132016-11-23 13:32:31 +01001738 LY_TREE_FOR(yin->child, child) {
1739 if (strcmp(child->ns->value, LY_NSYIN)) {
1740 /* extension */
1741 c_ext++;
1742 } else if (!strcmp(child->name, "if-feature")) {
1743 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001744 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001745 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001746 goto error;
1747 }
1748 }
1749
Radek Krejcie534c132016-11-23 13:32:31 +01001750 if (c_ftrs) {
1751 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001752 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001753 LOGMEM;
1754 goto error;
1755 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001756 }
Radek Krejcie534c132016-11-23 13:32:31 +01001757 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001758 /* some extensions may be already present from the substatements */
1759 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
1760 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001761 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001762 goto error;
1763 }
Radek Krejci5323b492017-01-16 15:40:11 +01001764 f->ext = reallocated;
1765
1766 /* init memory */
1767 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001768 }
1769
Radek Krejcie534c132016-11-23 13:32:31 +01001770 LY_TREE_FOR_SAFE(yin->child, next, child) {
1771 if (strcmp(child->ns->value, LY_NSYIN)) {
1772 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001773 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 +01001774 f->ext_size++;
1775 if (ret) {
1776 goto error;
1777 }
1778 } else { /* if-feature */
1779 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1780 f->iffeature_size++;
1781 if (ret) {
1782 goto error;
1783 }
1784 }
1785 }
1786
Radek Krejcic79c6b12016-07-26 15:11:49 +02001787 /* check for circular dependencies */
1788 if (f->iffeature_size) {
1789 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1790 goto error;
1791 }
1792 }
1793
Radek Krejci3cf9e222015-06-18 11:37:50 +02001794 return EXIT_SUCCESS;
1795
1796error:
1797
1798 return EXIT_FAILURE;
1799}
1800
Michal Vasko0d343d12015-08-24 14:57:36 +02001801/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001803fill_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 +02001804{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001808 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001809 if (!must->expr) {
1810 goto error;
1811 }
Radek Krejci800af702015-06-02 13:46:01 +02001812
Radek Krejcifdc0d702017-01-23 15:58:38 +01001813 return read_restr_substmt(module, LYEXT_PAR_RESTR, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001814
Michal Vasko77dc5652016-02-15 12:32:42 +01001815error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001817}
1818
Radek Krejci581ce772015-11-10 17:22:40 +01001819static int
Michal Vasko88c29542015-11-27 14:57:53 +01001820fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1821 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001822{
1823 int i, j;
1824 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001825 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001826
1827 /* get unique value (list of leafs supposed to be unique */
1828 GETVAL(value, yin, "tag");
1829
1830 /* count the number of unique leafs in the value */
1831 vaux = value;
1832 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001833 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001834 while (isspace(*vaux)) {
1835 vaux++;
1836 }
1837 }
1838 unique->expr_size++;
1839 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001840 if (!unique->expr) {
1841 LOGMEM;
1842 goto error;
1843 }
Radek Krejci581ce772015-11-10 17:22:40 +01001844
1845 for (i = 0; i < unique->expr_size; i++) {
1846 vaux = strpbrk(value, " \t\n");
1847 if (!vaux) {
1848 /* the last token, lydict_insert() will count its size on its own */
1849 vaux = value;
1850 }
1851
1852 /* store token into unique structure */
1853 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1854
1855 /* check that the expression does not repeat */
1856 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001857 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001858 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1859 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001860 goto error;
1861 }
1862 }
1863
1864 /* try to resolve leaf */
1865 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001866 unique_info = malloc(sizeof *unique_info);
1867 unique_info->list = parent;
1868 unique_info->expr = unique->expr[i];
1869 unique_info->trg_type = &unique->trg_type;
1870 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001871 goto error;
1872 }
Radek Krejci581ce772015-11-10 17:22:40 +01001873 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001874 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001875 goto error;
1876 }
1877 }
1878
1879 /* move to next token */
1880 value = vaux;
1881 while(isspace(*value)) {
1882 value++;
1883 }
1884 }
1885
1886 return EXIT_SUCCESS;
1887
1888error:
1889 return EXIT_FAILURE;
1890}
1891
Michal Vasko0d343d12015-08-24 14:57:36 +02001892/* logs directly
1893 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001894 * type: 0 - min, 1 - max
1895 */
1896static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001897deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001898{
1899 const char *value;
1900 char *endptr;
1901 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001902 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001903
Michal Vaskof7e57d52016-03-07 11:31:09 +01001904 /* del min/max is forbidden */
1905 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001906 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001907 goto error;
1908 }
1909
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001911 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001912 max = &((struct lys_node_leaflist *)target)->max;
1913 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001914 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001915 max = &((struct lys_node_list *)target)->max;
1916 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001917 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001918 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1919 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001920 goto error;
1921 }
1922
1923 GETVAL(value, node, "value");
1924 while (isspace(value[0])) {
1925 value++;
1926 }
1927
Radek Krejci0d7b2472016-02-12 11:11:03 +01001928 if (type && !strcmp(value, "unbounded")) {
1929 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001930 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001931 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001932 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001933 /* convert it to uint32_t */
1934 errno = 0;
1935 endptr = NULL;
1936 val = strtoul(value, &endptr, 10);
1937 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001938 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001939 goto error;
1940 }
1941 if (type) {
1942 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001943 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001944 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001945 } else {
1946 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001947 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001948 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001949 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001950 }
1951
1952 if (d->mod == LY_DEVIATE_ADD) {
1953 /* check that there is no current value */
1954 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001955 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1956 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 goto error;
1958 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001959 } else if (d->mod == LY_DEVIATE_RPL) {
1960 /* unfortunately, there is no way to check reliably that there
1961 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001962 }
1963
Michal Vaskof7e57d52016-03-07 11:31:09 +01001964 /* add (already checked) and replace */
1965 /* set new value specified in deviation */
1966 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001967
Pavol Vican09adcc32016-08-25 10:51:36 +02001968 /* check min-elements is smaller than max-elements */
1969 if (*max && *min > *max) {
1970 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001971 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001972 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1973 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001974 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001975 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1976 }
1977 goto error;
1978 }
1979
Radek Krejcieb00f512015-07-01 16:44:58 +02001980 return EXIT_SUCCESS;
1981
1982error:
1983
1984 return EXIT_FAILURE;
1985}
1986
Michal Vasko0d343d12015-08-24 14:57:36 +02001987/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001988static int
Michal Vasko88c29542015-11-27 14:57:53 +01001989fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1990 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001991{
1992 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01001993 struct lyxml_elem *next, *next2, *child, *develem;
1994 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001995 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001996 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001997 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001998 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001999 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002000 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002001 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002002 struct lys_node_leaf *leaf = NULL;
2003 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02002004 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002005 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002006 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002007 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002008 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002009 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002010 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02002011
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002012 ctx = module->ctx;
2013
Radek Krejcieb00f512015-07-01 16:44:58 +02002014 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002015 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002016 if (!dev->target_name) {
2017 goto error;
2018 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002019
2020 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01002021 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01002022 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002023 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002024 goto error;
2025 }
Radek Krejcic4283442016-04-22 09:19:27 +02002026 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002027 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2028 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002029 goto error;
2030 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002031
2032 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002033 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002034 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002035 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002036 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002037 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2038 /* extension */
2039 c_ext++;
2040 continue;
2041 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002042 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002043 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002044 goto error;
2045 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002046 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002047 if (!dev->dsc) {
2048 goto error;
2049 }
2050 } else if (!strcmp(child->name, "reference")) {
2051 if (dev->ref) {
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 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002055 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002056 if (!dev->ref) {
2057 goto error;
2058 }
2059 } else if (!strcmp(child->name, "deviate")) {
2060 c_dev++;
2061
Michal Vasko345da0a2015-12-02 10:35:55 +01002062 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002063 * further processed later
2064 */
2065 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002066
Radek Krejcieb00f512015-07-01 16:44:58 +02002067 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002068 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002069 goto error;
2070 }
2071
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002072 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002073 }
2074
2075 if (c_dev) {
2076 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01002077 if (!dev->deviate) {
2078 LOGMEM;
2079 goto error;
2080 }
Pavol Vican09adcc32016-08-25 10:51:36 +02002081 } else {
2082 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
2083 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002084 }
Radek Krejcie534c132016-11-23 13:32:31 +01002085 if (c_ext) {
2086 dev->ext = calloc(c_ext, sizeof *dev->ext);
2087 if (!dev->ext) {
2088 LOGMEM;
2089 goto error;
2090 }
2091 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002092
Radek Krejcie534c132016-11-23 13:32:31 +01002093
2094 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2095 if (strcmp(develem->ns->value, LY_NSYIN)) {
2096 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002097 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 +01002098 dev->ext_size++;
2099 if (rc) {
2100 goto error;
2101 }
2102 continue;
2103 }
2104
2105 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002106 /* init */
2107 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002108 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002109 c_must = 0;
2110 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002111 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002112 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002113
2114 /* get deviation type */
2115 GETVAL(value, develem, "value");
2116 if (!strcmp(value, "not-supported")) {
2117 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
2118 /* no property expected in this case */
2119 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002120 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002121 goto error;
2122 }
2123
Radek Krejci5b917642015-07-02 09:03:13 +02002124 /* and neither any other deviate statement is expected,
2125 * not-supported deviation must be the only deviation of the target
2126 */
2127 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002128 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2129 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002130 goto error;
2131 }
2132
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002133 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002134 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2135 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2136 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002137 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2138 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002139 goto error;
2140 }
2141 }
2142 }
Radek Krejci5b917642015-07-02 09:03:13 +02002143
Michal Vaskoff006c12016-02-17 11:15:19 +01002144 /* unlink and store the original node */
2145 lys_node_unlink(dev_target);
2146 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002147
Radek Krejci5b917642015-07-02 09:03:13 +02002148 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02002149 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02002150 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02002151 } else if (!strcmp(value, "add")) {
2152 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2153 } else if (!strcmp(value, "replace")) {
2154 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2155 } else if (!strcmp(value, "delete")) {
2156 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2157 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002158 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002159 goto error;
2160 }
2161 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002162 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002163
Michal Vaskoff006c12016-02-17 11:15:19 +01002164 /* store a shallow copy of the original node */
2165 if (!dev->orig_node) {
2166 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002167 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002168 /* just to be safe */
2169 if (tmp_unres.count) {
2170 LOGINT;
2171 goto error;
2172 }
2173 }
2174
Radek Krejcieb00f512015-07-01 16:44:58 +02002175 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002176 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002177 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2178 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002179 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002180 continue;
2181 }
2182
Radek Krejcieb00f512015-07-01 16:44:58 +02002183 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002184 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002185 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002186 goto error;
2187 }
2188
2189 /* for we deviate from RFC 6020 and allow config property even it is/is not
2190 * specified in the target explicitly since config property inherits. So we expect
2191 * that config is specified in every node. But for delete, we check that the value
2192 * is the same as here in deviation
2193 */
2194 GETVAL(value, child, "value");
2195 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002196 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002197 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002198 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002199 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002200 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002201 goto error;
2202 }
2203
2204 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002205 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002206 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002207 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002208 } else { /* add and replace are the same in this case */
2209 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002210 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002211
2212 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002213 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002214 }
2215 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002216 c_dflt++;
2217
2218 /* check target node type */
2219 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2220 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2221 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2222 goto error;
2223 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2224 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2225 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2226 goto error;
2227 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2228 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2229 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 goto error;
2231 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002232
Radek Krejcid5a5c282016-08-15 15:38:08 +02002233 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2234 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002235
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002237 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002238 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002239 goto error;
2240 }
2241
2242 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002243 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002244 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2245 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002246 goto error;
2247 }
2248
2249 GETVAL(value, child, "value");
2250 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002251 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002252 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002253 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002254 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002255 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002256 goto error;
2257 }
2258
2259 if (d->mod == LY_DEVIATE_ADD) {
2260 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002261 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002262 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2263 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002264 goto error;
2265 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002266
Radek Krejci841ec082016-04-05 13:05:17 +02002267 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002268 if (d->flags & LYS_MAND_TRUE) {
2269 if (dev_target->nodetype == LYS_CHOICE) {
2270 if (((struct lys_node_choice *)(dev_target))->dflt) {
2271 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2272 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2273 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2274 goto error;
2275 }
2276 } else if (dev_target->nodetype == LYS_LEAF) {
2277 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2278 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2279 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2280 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2281 goto error;
2282 }
2283 }
Radek Krejci841ec082016-04-05 13:05:17 +02002284 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002285
Michal Vasko21be1b32016-03-07 12:31:34 +01002286 dev_target->flags |= d->flags & LYS_MAND_MASK;
2287 } else if (d->mod == LY_DEVIATE_RPL) {
2288 /* check that there was a value before */
2289 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002290 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2291 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002292 goto error;
2293 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002294
Michal Vasko21be1b32016-03-07 12:31:34 +01002295 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002296 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002297 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002298 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002299 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002300 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002301 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002302
2303 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2304 for (parent = dev_target->parent;
2305 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2306 parent = parent->parent) {
2307 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2308 /* stop also on presence containers */
2309 break;
2310 }
2311 }
2312 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2313 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2314 if (lyp_check_mandatory_choice(parent)) {
2315 goto error;
2316 }
2317 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002318 } else if (!strcmp(child->name, "min-elements")) {
2319 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002320 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002321 goto error;
2322 }
2323 f_min = 1;
2324
Michal Vasko60f4b452016-02-12 11:02:55 +01002325 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002326 goto error;
2327 }
2328 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002329 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002330 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002331 goto error;
2332 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002333 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002334
Michal Vasko60f4b452016-02-12 11:02:55 +01002335 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002336 goto error;
2337 }
2338 } else if (!strcmp(child->name, "must")) {
2339 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002340 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002341 continue;
2342 } else if (!strcmp(child->name, "type")) {
2343 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002344 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002345 goto error;
2346 }
2347
Michal Vaskof7e57d52016-03-07 11:31:09 +01002348 /* add, del type is forbidden */
2349 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002350 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002351 goto error;
2352 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002353 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002354 goto error;
2355 }
2356
Radek Krejcieb00f512015-07-01 16:44:58 +02002357 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002358 if (dev_target->nodetype == LYS_LEAF) {
2359 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002360 if (((struct lys_node_leaf *)dev_target)->dflt) {
2361 ly_set_add(dflt_check, dev_target, 0);
2362 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002363 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2364 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002365 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2366 ly_set_add(dflt_check, dev_target, 0);
2367 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002368 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002369 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2370 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002371 goto error;
2372 }
2373
Radek Krejcieb00f512015-07-01 16:44:58 +02002374 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002375 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002376 /* HACK for unres */
2377 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002378 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002379 goto error;
2380 }
2381 d->type = t;
2382 } else if (!strcmp(child->name, "unique")) {
2383 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002384 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002385 continue;
2386 } else if (!strcmp(child->name, "units")) {
2387 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002388 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002389 goto error;
2390 }
2391
2392 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002393 if (dev_target->nodetype == LYS_LEAFLIST) {
2394 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2395 } else if (dev_target->nodetype == LYS_LEAF) {
2396 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002397 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002398 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2399 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002400 goto error;
2401 }
2402
2403 /* get units value */
2404 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002405 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002406
2407 /* apply to target */
2408 if (d->mod == LY_DEVIATE_ADD) {
2409 /* check that there is no current value */
2410 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002411 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2412 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002413 goto error;
2414 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002415
Michal Vasko21be1b32016-03-07 12:31:34 +01002416 *stritem = lydict_insert(ctx, value, 0);
2417 } else if (d->mod == LY_DEVIATE_RPL) {
2418 /* check that there was a value before */
2419 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002420 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2421 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002422 goto error;
2423 }
2424
2425 lydict_remove(ctx, *stritem);
2426 *stritem = lydict_insert(ctx, value, 0);
2427 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002428 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002429 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002430 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2431 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002432 goto error;
2433 }
2434 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002435 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002436 }
2437 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002438 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002439 goto error;
2440 }
2441
Michal Vasko88c29542015-11-27 14:57:53 +01002442 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002443 }
2444
2445 if (c_must) {
2446 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002447 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002448 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002449 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2450 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002451 break;
Radek Krejci76512572015-08-04 09:47:08 +02002452 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002453 trg_must = &((struct lys_node_container *)dev_target)->must;
2454 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002455 break;
Radek Krejci76512572015-08-04 09:47:08 +02002456 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002457 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2458 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002459 break;
Radek Krejci76512572015-08-04 09:47:08 +02002460 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002461 trg_must = &((struct lys_node_list *)dev_target)->must;
2462 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002463 break;
Radek Krejci76512572015-08-04 09:47:08 +02002464 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002465 case LYS_ANYDATA:
2466 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2467 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002468 break;
2469 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002470 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2471 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002472 goto error;
2473 }
2474
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002475 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002476
Radek Krejcieb00f512015-07-01 16:44:58 +02002477 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002478 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002479 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002480 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002481 } else if (d->mod == LY_DEVIATE_ADD) {
2482 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002483 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002484 if (!d->must) {
2485 LOGMEM;
2486 goto error;
2487 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002488 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002489 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002490 d->must_size = c_must;
2491 } else { /* LY_DEVIATE_DEL */
2492 d->must = calloc(c_must, sizeof *d->must);
2493 }
Michal Vasko253035f2015-12-17 16:58:13 +01002494 if (!d->must) {
2495 LOGMEM;
2496 goto error;
2497 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002498 }
2499 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002500 /* replace unique is forbidden */
2501 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002502 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002503 goto error;
2504 }
2505
Radek Krejcieb00f512015-07-01 16:44:58 +02002506 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002507 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002508 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2509 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002510 goto error;
2511 }
2512
Michal Vasko60f4b452016-02-12 11:02:55 +01002513 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002514 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002515 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002516 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002517 list->unique = d->unique;
2518 d->unique = &list->unique[list->unique_size];
2519 d->unique_size = c_uniq;
2520 } else { /* LY_DEVIATE_DEL */
2521 d->unique = calloc(c_uniq, sizeof *d->unique);
2522 }
Michal Vasko253035f2015-12-17 16:58:13 +01002523 if (!d->unique) {
2524 LOGMEM;
2525 goto error;
2526 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002527 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002528 if (c_dflt) {
2529 if (d->mod == LY_DEVIATE_ADD) {
2530 /* check that there is no current value */
2531 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2532 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2533 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2534 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2535 goto error;
2536 }
2537
2538 /* check collision with mandatory/min-elements */
2539 if ((dev_target->flags & LYS_MAND_TRUE) ||
2540 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2541 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2542 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2543 "Adding the \"default\" statement is forbidden on %s statement.",
2544 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2545 goto error;
2546 }
2547 } else if (d->mod == LY_DEVIATE_RPL) {
2548 /* check that there was a value before */
2549 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2550 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2551 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2552 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2553 goto error;
2554 }
2555 }
2556
2557 if (dev_target->nodetype == LYS_LEAFLIST) {
2558 /* reallocate default list in the target */
2559 llist = (struct lys_node_leaflist *)dev_target;
2560 if (d->mod == LY_DEVIATE_ADD) {
2561 /* reallocate (enlarge) the unique array of the target */
2562 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2563 } else if (d->mod == LY_DEVIATE_RPL) {
2564 /* reallocate (replace) the unique array of the target */
2565 for (i = 0; i < llist->dflt_size; i++) {
2566 lydict_remove(llist->module->ctx, llist->dflt[i]);
2567 }
2568 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2569 llist->dflt_size = 0;
2570 }
2571 }
2572 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2573 if (!d->dflt) {
2574 LOGMEM;
2575 goto error;
2576 }
2577 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002578
2579 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002580 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002581 if (!strcmp(child->name, "must")) {
2582 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002583 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 goto error;
2585 }
2586
2587 /* find must to delete, we are ok with just matching conditions */
2588 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002589 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002590 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002591 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002592 /* ... and maintain the array */
2593 (*trg_must_size)--;
2594 if (i != *trg_must_size) {
2595 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2596 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2597 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2598 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2599 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2600 }
2601 if (!(*trg_must_size)) {
2602 free(*trg_must);
2603 *trg_must = NULL;
2604 } else {
2605 (*trg_must)[*trg_must_size].expr = NULL;
2606 (*trg_must)[*trg_must_size].dsc = NULL;
2607 (*trg_must)[*trg_must_size].ref = NULL;
2608 (*trg_must)[*trg_must_size].eapptag = NULL;
2609 (*trg_must)[*trg_must_size].emsg = NULL;
2610 }
2611
2612 i = -1; /* set match flag */
2613 break;
2614 }
2615 }
2616 d->must_size++;
2617 if (i != -1) {
2618 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002619 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002620 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002621 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002622 goto error;
2623 }
2624 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002625 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002626 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002627 goto error;
2628 }
2629 (*trg_must_size)++;
2630 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002631
2632 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002633 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002634 goto error;
2635 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002636 } else if (!strcmp(child->name, "unique")) {
2637 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002638 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002639 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002640 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002641 goto error;
2642 }
2643
2644 /* find unique structures to delete */
2645 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002646 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002647 continue;
2648 }
2649
Radek Krejci581ce772015-11-10 17:22:40 +01002650 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002651 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002652 break;
2653 }
2654 }
2655
Radek Krejci581ce772015-11-10 17:22:40 +01002656 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002657 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002658 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002659 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002660 }
2661 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002662 /* ... and maintain the array */
2663 list->unique_size--;
2664 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002665 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2666 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002667 }
2668
2669 if (!list->unique_size) {
2670 free(list->unique);
2671 list->unique = NULL;
2672 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002673 list->unique[list->unique_size].expr_size = 0;
2674 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002675 }
2676
2677 i = -1; /* set match flag */
2678 break;
2679 }
2680 }
2681
2682 d->unique_size++;
2683 if (i != -1) {
2684 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002685 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2686 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002687 goto error;
2688 }
2689 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002690 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002691 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002692 list->unique_size++;
2693 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002694 goto error;
2695 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002696 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002697 } else if (!strcmp(child->name, "default")) {
2698 GETVAL(value, child, "value");
2699 u = strlen(value);
2700 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2701
2702 if (dev_target->nodetype == LYS_CHOICE) {
2703 choice = (struct lys_node_choice *)dev_target;
2704 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2705 if (rc || !node) {
2706 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2707 goto error;
2708 }
2709 if (d->mod == LY_DEVIATE_DEL) {
2710 if (!choice->dflt || (choice->dflt != node)) {
2711 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2712 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2713 goto error;
2714 }
2715 } else { /* add or replace */
2716 choice->dflt = node;
2717 if (!choice->dflt) {
2718 /* default branch not found */
2719 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2720 goto error;
2721 }
2722 }
2723 } else if (dev_target->nodetype == LYS_LEAF) {
2724 leaf = (struct lys_node_leaf *)dev_target;
2725 if (d->mod == LY_DEVIATE_DEL) {
2726 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2727 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2728 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2729 goto error;
2730 }
2731 /* remove value */
2732 lydict_remove(ctx, leaf->dflt);
2733 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002734 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002735 } else { /* add (already checked) and replace */
2736 /* remove value */
2737 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002738 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002739
2740 /* set new value */
2741 leaf->dflt = lydict_insert(ctx, value, u);
2742
Radek Krejcibd117f02016-11-04 16:28:08 +01002743 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002744 ly_set_add(dflt_check, dev_target, 0);
2745 }
2746 } else { /* LYS_LEAFLIST */
2747 llist = (struct lys_node_leaflist *)dev_target;
2748 if (d->mod == LY_DEVIATE_DEL) {
2749 /* find and remove the value in target list */
2750 for (i = 0; i < llist->dflt_size; i++) {
2751 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2752 /* match, remove the value */
2753 lydict_remove(llist->module->ctx, llist->dflt[i]);
2754 llist->dflt[i] = NULL;
2755 break;
2756 }
2757 }
2758 if (i == llist->dflt_size) {
2759 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2760 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2761 goto error;
2762 }
2763 } else {
2764 /* add or replace, anyway we place items into the deviate's list
2765 which propagates to the target */
2766 /* we just want to check that the value isn't already in the list */
2767 for (i = 0; i < llist->dflt_size; i++) {
2768 if (ly_strequal(llist->dflt[i], value, 1)) {
2769 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2770 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2771 goto error;
2772 }
2773 }
2774 /* store it in target node */
2775 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2776
2777 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2778 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01002779 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002780 }
2781 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002782 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002783 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002784
2785 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2786 /* consolidate the final list in the target after removing items from it */
2787 llist = (struct lys_node_leaflist *)dev_target;
2788 for (i = j = 0; j < llist->dflt_size; j++) {
2789 llist->dflt[i] = llist->dflt[j];
2790 if (llist->dflt[i]) {
2791 i++;
2792 }
2793 }
2794 llist->dflt_size = i + 1;
2795 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002796 }
2797
Michal Vasko43a1feb2016-03-07 12:03:02 +01002798 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002799 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002800 value = NULL;
2801 rc = EXIT_SUCCESS;
2802 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2803 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002804 value = leaf->dflt;
2805 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002806 } else { /* LYS_LEAFLIST */
2807 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2808 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002809 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2810 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002811 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002812 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002813 break;
2814 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002815 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002816
2817 }
2818 if (rc == -1) {
2819 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2820 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2821 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2822 dev->target_name);
2823 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002824 }
2825 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002826
Radek Krejci27fe55e2016-09-13 17:13:35 +02002827 /* mark all the affected modules as deviated and implemented */
2828 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2829 mod = lys_node_module(parent);
2830 if (module != mod) {
2831 mod->deviated = 1;
2832 lys_set_implemented(mod);
2833 }
2834 }
2835
Radek Krejcid5a5c282016-08-15 15:38:08 +02002836 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002837 return EXIT_SUCCESS;
2838
2839error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002840 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002841 return EXIT_FAILURE;
2842}
2843
Michal Vasko0d343d12015-08-24 14:57:36 +02002844/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002845static int
Radek Krejcib8048692015-08-05 13:36:34 +02002846fill_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 +02002847 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002848{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002850 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002851 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002852 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01002853 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02002854
Michal Vasko591e0b22015-08-13 13:53:43 +02002855 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002857 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002858 if (!aug->target_name) {
2859 goto error;
2860 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002862
Radek Krejci07d0fb92017-01-13 14:11:05 +01002863 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002864 goto error;
2865 }
2866
Radek Krejcie534c132016-11-23 13:32:31 +01002867 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2868 if (strcmp(sub->ns->value, LY_NSYIN)) {
2869 /* extension */
2870 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002871 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01002872 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01002873 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002874 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002875 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002876 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002877 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002878 goto error;
2879 }
2880
Radek Krejci5323b492017-01-16 15:40:11 +01002881 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002882 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002883 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002884 goto error;
2885 }
Radek Krejcie534c132016-11-23 13:32:31 +01002886 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002887 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002888
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002889 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01002890 } else if (!strcmp(sub->name, "container")) {
2891 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
2892 } else if (!strcmp(sub->name, "leaf-list")) {
2893 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
2894 } else if (!strcmp(sub->name, "leaf")) {
2895 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
2896 } else if (!strcmp(sub->name, "list")) {
2897 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
2898 } else if (!strcmp(sub->name, "uses")) {
2899 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
2900 } else if (!strcmp(sub->name, "choice")) {
2901 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
2902 } else if (!strcmp(sub->name, "case")) {
2903 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
2904 } else if (!strcmp(sub->name, "anyxml")) {
2905 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
2906 } else if (!strcmp(sub->name, "anydata")) {
2907 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
2908 } else if (!strcmp(sub->name, "action")) {
2909 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
2910 } else if (!strcmp(sub->name, "notification")) {
2911 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002912 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01002913 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002914 goto error;
2915 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002916
Radek Krejci1d82ef62015-08-07 14:44:40 +02002917 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002918 goto error;
2919 }
2920
Radek Krejci1d82ef62015-08-07 14:44:40 +02002921 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002922 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002923 }
2924
Radek Krejcie534c132016-11-23 13:32:31 +01002925 if (c_ftrs) {
2926 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002927 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002928 LOGMEM;
2929 goto error;
2930 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002931 }
Radek Krejcie534c132016-11-23 13:32:31 +01002932 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01002933 /* some extensions may be already present from the substatements */
2934 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
2935 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01002936 LOGMEM;
2937 goto error;
2938 }
Radek Krejci30701b42017-01-23 16:41:38 +01002939 aug->ext = reallocated;
2940
2941 /* init memory */
2942 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01002943 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002944
Radek Krejcie534c132016-11-23 13:32:31 +01002945 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2946 if (strcmp(sub->ns->value, LY_NSYIN)) {
2947 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002948 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 +01002949 aug->ext_size++;
2950 if (ret) {
2951 goto error;
2952 }
2953 } else if (!strcmp(sub->name, "if-feature")) {
2954 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002955 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002956 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002957 goto error;
2958 }
Radek Krejcie534c132016-11-23 13:32:31 +01002959 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002960 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002961 }
2962
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002963 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002964 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002965 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002966 * when the uses does and cannot be resolved now for sure
2967 * (the grouping was not yet copied into uses).
2968 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002969 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002970 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002971 goto error;
2972 }
Michal Vasko49291b32015-08-06 09:49:41 +02002973 }
Radek Krejci106efc02015-06-10 14:36:27 +02002974
Michal Vasko508a50d2016-09-07 14:50:33 +02002975 /* check XPath dependencies */
2976 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2977 goto error;
2978 }
2979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002981
2982error:
2983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002984 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002985}
2986
Michal Vasko0d343d12015-08-24 14:57:36 +02002987/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002989fill_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 +02002990{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002991 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 struct lyxml_elem *sub, *next;
2993 const char *value;
2994 char *endptr;
2995 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002996 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 int r;
2998 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002999 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003000
Radek Krejci363bd4a2016-07-29 14:30:20 +02003001 assert(uses);
3002 module = uses->module; /* shorthand */
3003
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003004 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003005 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003006 if (!rfn->target_name) {
3007 goto error;
3008 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003009
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003011 if (!sub->ns) {
3012 /* garbage */
3013 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003014 /* extension */
3015 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003016 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003017
Radek Krejci411b1bf2017-01-23 16:40:05 +01003018 } else if (!strcmp(sub->name, "description")) {
3019 if (rfn->dsc) {
3020 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3021 goto error;
3022 }
3023
3024 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3025 goto error;
3026 }
3027
3028 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3029 if (!rfn->dsc) {
3030 goto error;
3031 }
3032 } else if (!strcmp(sub->name, "reference")) {
3033 if (rfn->ref) {
3034 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3035 goto error;
3036 }
3037
3038 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3039 goto error;
3040 }
3041
3042 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3043 if (!rfn->ref) {
3044 goto error;
3045 }
3046 } else if (!strcmp(sub->name, "config")) {
3047 if (rfn->flags & LYS_CONFIG_MASK) {
3048 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3049 goto error;
3050 }
3051 GETVAL(value, sub, "value");
3052 if (!strcmp(value, "false")) {
3053 rfn->flags |= LYS_CONFIG_R;
3054 } else if (!strcmp(value, "true")) {
3055 rfn->flags |= LYS_CONFIG_W;
3056 } else {
3057 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3058 goto error;
3059 }
3060 rfn->flags |= LYS_CONFIG_SET;
3061
3062 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
3063 goto error;
3064 }
Radek Krejcie534c132016-11-23 13:32:31 +01003065 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003066 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 /* check possibility of statements combination */
3069 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003070 if (c_dflt) {
3071 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003072 if (module->version < 2) {
3073 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3074 goto error;
3075 }
Radek Krejci200bf712016-08-16 17:11:04 +02003076 rfn->target_type &= LYS_LEAFLIST;
3077 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003078 if (module->version < 2) {
3079 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3080 } else {
3081 /* YANG 1.1 */
3082 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3083 }
Radek Krejci200bf712016-08-16 17:11:04 +02003084 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003086 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3087 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 goto error;
3089 }
3090 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003091 if (module->version < 2) {
3092 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3093 } else {
3094 /* YANG 1.1 */
3095 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3096 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003097 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003098
Radek Krejcifdc0d702017-01-23 15:58:38 +01003099 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
3100 goto error;
3101 }
Radek Krejci200bf712016-08-16 17:11:04 +02003102 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003103 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 } else if (!strcmp(sub->name, "mandatory")) {
3105 /* leaf, choice or anyxml */
3106 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003107 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003108 goto error;
3109 }
3110 /* just checking the flags in leaf is not sufficient, we would allow
3111 * multiple mandatory statements with the "false" value
3112 */
3113 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 /* check possibility of statements combination */
3116 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003117 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003119 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3120 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 goto error;
3122 }
3123 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003124 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 GETVAL(value, sub, "value");
3128 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003129 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003131 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003133 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003134 goto error;
3135 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003136 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
3137 goto error;
3138 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 } else if (!strcmp(sub->name, "min-elements")) {
3140 /* list or leaf-list */
3141 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003142 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003143 goto error;
3144 }
3145 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003147 /* check possibility of statements combination */
3148 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003149 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
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 {
Radek Krejci76512572015-08-04 09:47:08 +02003156 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003157 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 GETVAL(value, sub, "value");
3160 while (isspace(value[0])) {
3161 value++;
3162 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 /* convert it to uint32_t */
3165 errno = 0;
3166 endptr = NULL;
3167 val = strtoul(value, &endptr, 10);
3168 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003169 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 goto error;
3171 }
3172 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003173 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003174
3175 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
3176 goto error;
3177 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 } else if (!strcmp(sub->name, "max-elements")) {
3179 /* list or leaf-list */
3180 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003181 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 goto error;
3183 }
3184 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 /* check possibility of statements combination */
3187 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003188 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003189 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003190 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3191 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 goto error;
3193 }
3194 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003195 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003196 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 GETVAL(value, sub, "value");
3199 while (isspace(value[0])) {
3200 value++;
3201 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003202
Radek Krejci0d7b2472016-02-12 11:11:03 +01003203 if (!strcmp(value, "unbounded")) {
3204 rfn->mod.list.max = 0;
3205 } else {
3206 /* convert it to uint32_t */
3207 errno = 0;
3208 endptr = NULL;
3209 val = strtoul(value, &endptr, 10);
3210 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003211 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003212 goto error;
3213 }
3214 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003216 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003217
3218 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
3219 goto error;
3220 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 } else if (!strcmp(sub->name, "presence")) {
3222 /* container */
3223 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 /* check possibility of statements combination */
3229 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003230 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003232 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3233 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 goto error;
3235 }
3236 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003237 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 GETVAL(value, sub, "value");
3241 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003242
3243 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
3244 goto error;
3245 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003246 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003247 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003248 /* check possibility of statements combination */
3249 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003250 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003252 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3253 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 goto error;
3255 }
3256 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003257 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003261 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003262
Radek Krejci363bd4a2016-07-29 14:30:20 +02003263 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3264 /* leaf, leaf-list, list, container or anyxml */
3265 /* check possibility of statements combination */
3266 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003267 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003268 if (!rfn->target_type) {
3269 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3270 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3271 goto error;
3272 }
3273 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003274 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003275 }
3276
3277 c_ftrs++;
3278 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003280 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 goto error;
3282 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003283
Michal Vasko345da0a2015-12-02 10:35:55 +01003284 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003287 /* process nodes with cardinality of 0..n */
3288 if (c_must) {
3289 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003290 if (!rfn->must) {
3291 LOGMEM;
3292 goto error;
3293 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003295 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003296 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003297 if (!rfn->iffeature) {
3298 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003299 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 }
Radek Krejci200bf712016-08-16 17:11:04 +02003302 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003303 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003304 if (!rfn->dflt) {
3305 LOGMEM;
3306 goto error;
3307 }
3308 }
Radek Krejcie534c132016-11-23 13:32:31 +01003309 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003310 /* some extensions may be already present from the substatements */
3311 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3312 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003313 LOGMEM;
3314 goto error;
3315 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003316 rfn->ext = reallocated;
3317
3318 /* init memory */
3319 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003320 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003321
Radek Krejcie534c132016-11-23 13:32:31 +01003322 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3323 if (strcmp(sub->ns->value, LY_NSYIN)) {
3324 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003325 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 +01003326 rfn->ext_size++;
3327 if (r) {
3328 goto error;
3329 }
3330 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003331 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003332 rfn->iffeature_size++;
3333 if (r) {
3334 goto error;
3335 }
Radek Krejci200bf712016-08-16 17:11:04 +02003336 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003337 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003338 rfn->must_size++;
3339 if (r) {
3340 goto error;
3341 }
Radek Krejci200bf712016-08-16 17:11:04 +02003342 } else { /* default */
3343 GETVAL(value, sub, "value");
3344
3345 /* check for duplicity */
3346 for (r = 0; r < rfn->dflt_size; r++) {
3347 if (ly_strequal(rfn->dflt[r], value, 1)) {
3348 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3349 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3350 goto error;
3351 }
3352 }
3353 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003354 }
3355 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003358
3359error:
3360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003362}
3363
Michal Vasko0d343d12015-08-24 14:57:36 +02003364/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365static int
Radek Krejcie534c132016-11-23 13:32:31 +01003366fill_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 +02003367{
Radek Krejcie534c132016-11-23 13:32:31 +01003368 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003370 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003371 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003372
Radek Krejcie534c132016-11-23 13:32:31 +01003373 /* init */
3374 memset(&exts, 0, sizeof exts);
3375
3376 LY_TREE_FOR_SAFE(yin->child, next, child) {
3377 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003378 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003379 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003380 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3381 /* extension */
3382 c_ext++;
3383 lyxml_unlink_elem(module->ctx, child, 2);
3384 lyxml_add_child(module->ctx, &exts, child);
3385 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003387 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 goto error;
3389 }
3390 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003391
3392 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
3393 goto error;
3394 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 } else if (!strcmp(child->name, "revision-date")) {
3396 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003397 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3398 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 }
3400 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003401 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003402 goto error;
3403 }
3404 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003405
3406 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
3407 goto error;
3408 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003409 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003410 if (imp->dsc) {
3411 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3412 goto error;
3413 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003414 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3415 goto error;
3416 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003417 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3418 if (!imp->dsc) {
3419 goto error;
3420 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003421 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003422 if (imp->ref) {
3423 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3424 goto error;
3425 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003426 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3427 goto error;
3428 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003429 imp->ref = read_yin_subnode(module->ctx, child, "text");
3430 if (!imp->ref) {
3431 goto error;
3432 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003434 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 goto error;
3436 }
3437 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 /* check mandatory information */
3440 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003441 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 goto error;
3443 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003444
Radek Krejcie534c132016-11-23 13:32:31 +01003445 /* process extensions */
3446 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003447 /* some extensions may be already present from the substatements */
3448 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3449 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003450 LOGMEM;
3451 goto error;
3452 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003453 imp->ext = reallocated;
3454
3455 /* init memory */
3456 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3457
Radek Krejcie534c132016-11-23 13:32:31 +01003458 LY_TREE_FOR_SAFE(exts.child, next, child) {
3459 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003460 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 +01003461 imp->ext_size++;
3462 if (r) {
3463 goto error;
3464 }
3465 }
3466 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003467
Radek Krejcie534c132016-11-23 13:32:31 +01003468 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003469 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003470
3471error:
3472
Radek Krejcie534c132016-11-23 13:32:31 +01003473 while (exts.child) {
3474 lyxml_free(module->ctx, exts.child);
3475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003477}
3478
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003479/* logs directly
3480 * returns:
3481 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003482 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003483 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003485fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3486 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003487{
Radek Krejcie534c132016-11-23 13:32:31 +01003488 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003490 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003491 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003492
Radek Krejcie534c132016-11-23 13:32:31 +01003493 /* init */
3494 memset(&exts, 0, sizeof exts);
3495
3496 LY_TREE_FOR_SAFE(yin->child, next, child) {
3497 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003498 /* garbage */
3499 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003500 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3501 /* extension */
3502 c_ext++;
3503 lyxml_unlink_elem(module->ctx, child, 2);
3504 lyxml_add_child(module->ctx, &exts, child);
3505 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003507 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 goto error;
3509 }
3510 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003511 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 goto error;
3513 }
3514 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003515
3516 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
3517 goto error;
3518 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003519 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003520 if (inc->dsc) {
3521 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3522 goto error;
3523 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003524 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3525 goto error;
3526 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003527 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3528 if (!inc->dsc) {
3529 goto error;
3530 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003531 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003532 if (inc->ref) {
3533 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3534 goto error;
3535 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003536 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3537 goto error;
3538 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003539 inc->ref = read_yin_subnode(module->ctx, child, "text");
3540 if (!inc->ref) {
3541 goto error;
3542 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003544 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 goto error;
3546 }
3547 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003548
Radek Krejcie534c132016-11-23 13:32:31 +01003549 /* process extensions */
3550 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003551 /* some extensions may be already present from the substatements */
3552 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3553 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003554 LOGMEM;
3555 goto error;
3556 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003557 inc->ext = reallocated;
3558
3559 /* init memory */
3560 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3561
Radek Krejcie534c132016-11-23 13:32:31 +01003562 LY_TREE_FOR_SAFE(exts.child, next, child) {
3563 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003564 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 +01003565 inc->ext_size++;
3566 if (r) {
3567 goto error;
3568 }
3569 }
3570 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003571
Radek Krejcie534c132016-11-23 13:32:31 +01003572 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003573 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003574
3575error:
3576
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003577 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003578}
3579
Michal Vasko0d343d12015-08-24 14:57:36 +02003580/* logs directly
3581 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003582 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003583 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003584 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003585 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003587read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3588 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003589{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003590 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003591 const char *value;
3592 struct lyxml_elem *sub, *next;
3593 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003596 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 if (opt & OPT_IDENT) {
3600 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003601 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 goto error;
3603 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003604 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 /* process local parameters */
3608 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003609 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003610 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003611 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003612 continue;
3613 }
3614 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003615 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003616 continue;
3617 }
3618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003620 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003621 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 goto error;
3623 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003624
Radek Krejciac00b2a2017-01-17 14:05:00 +01003625 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003626 goto error;
3627 }
3628
Radek Krejci1d82ef62015-08-07 14:44:40 +02003629 node->dsc = read_yin_subnode(ctx, sub, "text");
3630 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003631 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 }
3633 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003634 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003635 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 goto error;
3637 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003638
Radek Krejciac00b2a2017-01-17 14:05:00 +01003639 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003640 goto error;
3641 }
3642
Radek Krejci1d82ef62015-08-07 14:44:40 +02003643 node->ref = read_yin_subnode(ctx, sub, "text");
3644 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003645 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003646 }
3647 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003648 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003649 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 goto error;
3651 }
3652 GETVAL(value, sub, "value");
3653 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003654 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003656 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003658 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003660 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003661 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003662 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003663
Radek Krejciac00b2a2017-01-17 14:05:00 +01003664 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003665 goto error;
3666 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003667 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3668 if (opt & OPT_CFG_PARSE) {
3669 if (node->flags & LYS_CONFIG_MASK) {
3670 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3671 goto error;
3672 }
3673 GETVAL(value, sub, "value");
3674 if (!strcmp(value, "false")) {
3675 node->flags |= LYS_CONFIG_R;
3676 } else if (!strcmp(value, "true")) {
3677 node->flags |= LYS_CONFIG_W;
3678 } else {
3679 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3680 goto error;
3681 }
3682 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003683
Radek Krejciac00b2a2017-01-17 14:05:00 +01003684 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003685 goto error;
3686 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003689 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 continue;
3691 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003692 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003694
Michal Vaskoe022a562016-09-27 14:24:15 +02003695 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003697 if (parent) {
3698 node->flags |= parent->flags & LYS_CONFIG_MASK;
3699 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003701 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 }
3703 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003706
3707error:
3708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003710}
3711
Michal Vasko0d343d12015-08-24 14:57:36 +02003712/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003713static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003714read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003715{
Radek Krejci76512572015-08-04 09:47:08 +02003716 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003717 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003718 const char *value;
3719
3720 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003721 if (!retval) {
3722 LOGMEM;
3723 return NULL;
3724 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003725
3726 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003727 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003728 if (!retval->cond) {
3729 goto error;
3730 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003731
Radek Krejci5323b492017-01-16 15:40:11 +01003732 LY_TREE_FOR_SAFE(yin->child, next, child) {
3733 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003734 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003735 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003736 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3737 /* extensions */
Radek Krejciac00b2a2017-01-17 14:05:00 +01003738 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003739 goto error;
3740 }
3741 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003742 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003743 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003744 goto error;
3745 }
Radek Krejci5323b492017-01-16 15:40:11 +01003746
Radek Krejciac00b2a2017-01-17 14:05:00 +01003747 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003748 goto error;
3749 }
3750
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003751 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3752 if (!retval->dsc) {
3753 goto error;
3754 }
3755 } else if (!strcmp(child->name, "reference")) {
3756 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003757 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003758 goto error;
3759 }
Radek Krejci5323b492017-01-16 15:40:11 +01003760
Radek Krejciac00b2a2017-01-17 14:05:00 +01003761 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003762 goto error;
3763 }
3764
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003765 retval->ref = read_yin_subnode(module->ctx, child, "text");
3766 if (!retval->ref) {
3767 goto error;
3768 }
3769 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003770 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003771 goto error;
3772 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003773 }
3774
3775 return retval;
3776
3777error:
3778
Michal Vasko0308dd62015-10-07 09:14:40 +02003779 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003780 return NULL;
3781}
3782
Michal Vasko0d343d12015-08-24 14:57:36 +02003783/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003784static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003785read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003786 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003787{
Michal Vasko29fc0182015-08-24 15:02:39 +02003788 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003789 struct lys_node_case *cs;
3790 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003791 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003792 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003793
Radek Krejcie867c852015-08-27 09:52:34 +02003794 /* init */
3795 memset(&root, 0, sizeof root);
3796
Radek Krejci1d82ef62015-08-07 14:44:40 +02003797 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003798 if (!cs) {
3799 LOGMEM;
3800 return NULL;
3801 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003802 cs->nodetype = LYS_CASE;
3803 cs->prev = (struct lys_node *)cs;
3804 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003805
Radek Krejci07d0fb92017-01-13 14:11:05 +01003806 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3807 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 goto error;
3809 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003810
Radek Krejcia9544502015-08-14 08:24:29 +02003811 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3812
Michal Vasko3a0043f2015-08-12 12:11:30 +02003813 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003814 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003815 goto error;
3816 }
3817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 /* process choice's specific children */
3819 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003820 if (strcmp(sub->ns->value, LY_NSYIN)) {
3821 /* extension */
3822 c_ext++;
3823 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003824 !strcmp(sub->name, "leaf-list") ||
3825 !strcmp(sub->name, "leaf") ||
3826 !strcmp(sub->name, "list") ||
3827 !strcmp(sub->name, "uses") ||
3828 !strcmp(sub->name, "choice") ||
3829 !strcmp(sub->name, "anyxml")) {
3830
Michal Vaskof3930de2015-10-22 12:03:59 +02003831 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003832 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003833 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003834 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003835 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003837 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003838 goto error;
3839 }
3840
Radek Krejci5323b492017-01-16 15:40:11 +01003841 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003842 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003843 goto error;
3844 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003845
Michal Vasko345da0a2015-12-02 10:35:55 +01003846 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003848 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003852
Radek Krejci3cf9e222015-06-18 11:37:50 +02003853 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003854 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3855 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003856 LOGMEM;
3857 goto error;
3858 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003859 }
Radek Krejcie534c132016-11-23 13:32:31 +01003860 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01003861 /* some extensions may be already present from the substatements */
3862 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
3863 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003864 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003865 goto error;
3866 }
Radek Krejci21c81652017-01-23 10:42:55 +01003867 retval->ext = reallocated;
3868
3869 /* init memory */
3870 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 }
Radek Krejci21c81652017-01-23 10:42:55 +01003872
Radek Krejcie534c132016-11-23 13:32:31 +01003873 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3874 if (strcmp(sub->ns->value, LY_NSYIN)) {
3875 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003876 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 +01003877 retval->ext_size++;
3878 if (ret) {
3879 goto error;
3880 }
3881 } else {
3882 /* if-feature */
3883 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3884 cs->iffeature_size++;
3885 if (ret) {
3886 goto error;
3887 }
3888 }
3889 }
Radek Krejcib388c152015-06-04 17:03:03 +02003890
Michal Vasko29fc0182015-08-24 15:02:39 +02003891 /* last part - process data nodes */
3892 LY_TREE_FOR_SAFE(root.child, next, sub) {
3893 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003894 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003895 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003896 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003897 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003898 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003899 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003900 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003901 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003902 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003903 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003904 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003905 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003906 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003907 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003908 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003909 }
3910 if (!node) {
3911 goto error;
3912 }
3913
Michal Vasko345da0a2015-12-02 10:35:55 +01003914 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003915 }
3916
Michal Vasko508a50d2016-09-07 14:50:33 +02003917 /* check XPath dependencies */
3918 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3919 goto error;
3920 }
3921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003923
3924error:
3925
Michal Vasko29fc0182015-08-24 15:02:39 +02003926 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003927 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003928 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003929 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003931 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003932}
3933
Michal Vasko0d343d12015-08-24 14:57:36 +02003934/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003935static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003936read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3937 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003938{
Radek Krejci629cdef2016-06-06 15:06:36 +02003939 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003940 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003942 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003943 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003944 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003945 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003948 if (!choice) {
3949 LOGMEM;
3950 return NULL;
3951 }
Radek Krejci76512572015-08-04 09:47:08 +02003952 choice->nodetype = LYS_CHOICE;
3953 choice->prev = (struct lys_node *)choice;
3954 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003955
Radek Krejci07d0fb92017-01-13 14:11:05 +01003956 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3957 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 goto error;
3959 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
Radek Krejcia9544502015-08-14 08:24:29 +02003961 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3962
Michal Vasko3a0043f2015-08-12 12:11:30 +02003963 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003964 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003965 goto error;
3966 }
3967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 /* process choice's specific children */
3969 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003970 if (strcmp(sub->ns->value, LY_NSYIN)) {
3971 /* extension */
3972 c_ext++;
3973 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003974 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003975 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003976 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 goto error;
3978 }
3979 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003980 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003981 goto error;
3982 }
3983 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003984 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 goto error;
3986 }
3987 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003988 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 goto error;
3990 }
3991 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003992 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003993 goto error;
3994 }
3995 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003996 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003997 goto error;
3998 }
3999 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004000 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 goto error;
4002 }
4003 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004004 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004005 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004006 goto error;
4007 }
Radek Krejci21c81652017-01-23 10:42:55 +01004008
4009 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4010 goto error;
4011 }
4012
Radek Krejci629cdef2016-06-06 15:06:36 +02004013 dflt = sub;
4014 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004015 continue;
4016 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004018 } else if (!strcmp(sub->name, "mandatory")) {
4019 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004020 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 goto error;
4022 }
4023 /* just checking the flags in leaf is not sufficient, we would allow
4024 * multiple mandatory statements with the "false" value
4025 */
4026 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 GETVAL(value, sub, "value");
4029 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004030 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004031 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004032 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004033 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004034 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 goto error;
4036 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004037
4038 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
4039 goto error;
4040 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004041 } else if (!strcmp(sub->name, "when")) {
4042 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004043 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004044 goto error;
4045 }
4046
Radek Krejci5323b492017-01-16 15:40:11 +01004047 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004048 if (!choice->when) {
4049 goto error;
4050 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004051 } else if (!strcmp(sub->name, "if-feature")) {
4052 c_ftrs++;
4053
Michal Vasko345da0a2015-12-02 10:35:55 +01004054 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004055 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004056 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004057 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004058 goto error;
4059 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004060 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004061 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004063 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004064
Radek Krejci1d82ef62015-08-07 14:44:40 +02004065 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004066 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004067 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004068
Radek Krejci3cf9e222015-06-18 11:37:50 +02004069 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004070 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4071 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004072 LOGMEM;
4073 goto error;
4074 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004075 }
Radek Krejcie534c132016-11-23 13:32:31 +01004076 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004077 /* some extensions may be already present from the substatements */
4078 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4079 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004080 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004081 goto error;
4082 }
Radek Krejci21c81652017-01-23 10:42:55 +01004083 retval->ext = reallocated;
4084
4085 /* init memory */
4086 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004087 }
4088
Radek Krejcie534c132016-11-23 13:32:31 +01004089 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4090 if (strcmp(sub->ns->value, LY_NSYIN)) {
4091 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004092 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 +01004093 retval->ext_size++;
4094 if (ret) {
4095 goto error;
4096 }
4097 } else {
4098 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4099 choice->iffeature_size++;
4100 if (ret) {
4101 goto error;
4102 }
4103 }
4104 }
4105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004107 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004108 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004109 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004110 goto error;
4111 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004113 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004114 if (dflt) {
4115 GETVAL(value, dflt, "value");
4116 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004117 goto error;
4118 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004119 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004120 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004121
Michal Vasko508a50d2016-09-07 14:50:33 +02004122 /* check XPath dependencies */
4123 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4124 goto error;
4125 }
4126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004127 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004128
4129error:
4130
Radek Krejci629cdef2016-06-06 15:06:36 +02004131 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004132 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004134 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004135}
4136
Michal Vasko0d343d12015-08-24 14:57:36 +02004137/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004138static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004139read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
4140 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004141{
Radek Krejci76512572015-08-04 09:47:08 +02004142 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004143 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004144 struct lyxml_elem *sub, *next;
4145 const char *value;
4146 int r;
4147 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004148 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004149 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004152 if (!anyxml) {
4153 LOGMEM;
4154 return NULL;
4155 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004156 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004157 anyxml->prev = (struct lys_node *)anyxml;
4158 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004159
Radek Krejci07d0fb92017-01-13 14:11:05 +01004160 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4161 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004162 goto error;
4163 }
Radek Krejci863c2852015-06-03 15:47:11 +02004164
Radek Krejcia9544502015-08-14 08:24:29 +02004165 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004166
Radek Krejcic189a952016-07-11 15:27:07 +02004167 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004168 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004169 goto error;
4170 }
4171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004173 if (strcmp(sub->ns->value, LY_NSYIN)) {
4174 /* extension */
4175 c_ext++;
4176 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004178 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004179 goto error;
4180 }
4181 /* just checking the flags in leaf is not sufficient, we would allow
4182 * multiple mandatory statements with the "false" value
4183 */
4184 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004186 GETVAL(value, sub, "value");
4187 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004188 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004189 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004190 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004191 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004192 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004193 goto error;
4194 }
4195 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004196
4197 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
4198 goto error;
4199 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004200 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004201 } else if (!strcmp(sub->name, "when")) {
4202 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004203 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004204 goto error;
4205 }
4206
Radek Krejci5323b492017-01-16 15:40:11 +01004207 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004208 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004209 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004210 goto error;
4211 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004212 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004213 } else if (!strcmp(sub->name, "must")) {
4214 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004215 } else if (!strcmp(sub->name, "if-feature")) {
4216 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004218 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004219 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004220 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004221 }
4222 }
Radek Krejci863c2852015-06-03 15:47:11 +02004223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004224 /* middle part - process nodes with cardinality of 0..n */
4225 if (c_must) {
4226 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004227 if (!anyxml->must) {
4228 LOGMEM;
4229 goto error;
4230 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004231 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004232 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004233 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4234 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004235 LOGMEM;
4236 goto error;
4237 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004238 }
Radek Krejcie534c132016-11-23 13:32:31 +01004239 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004240 /* some extensions may be already present from the substatements */
4241 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4242 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004243 LOGMEM;
4244 goto error;
4245 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004246 retval->ext = reallocated;
4247
4248 /* init memory */
4249 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004250 }
Radek Krejci863c2852015-06-03 15:47:11 +02004251
Radek Krejcie534c132016-11-23 13:32:31 +01004252 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4253 if (strcmp(sub->ns->value, LY_NSYIN)) {
4254 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004255 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 +01004256 retval->ext_size++;
4257 if (r) {
4258 goto error;
4259 }
4260 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004261 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004262 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004263 if (r) {
4264 goto error;
4265 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004266 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004267 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004268 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004269 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004270 goto error;
4271 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004272 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004273 }
Radek Krejci863c2852015-06-03 15:47:11 +02004274
Michal Vasko508a50d2016-09-07 14:50:33 +02004275 /* check XPath dependencies */
4276 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4277 goto error;
4278 }
4279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004281
4282error:
4283
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004284 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004287}
4288
Michal Vasko0d343d12015-08-24 14:57:36 +02004289/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004290static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004291read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004292 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004293{
Radek Krejci76512572015-08-04 09:47:08 +02004294 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004295 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 struct lyxml_elem *sub, *next;
4297 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004298 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004299 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004300 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004303 if (!leaf) {
4304 LOGMEM;
4305 return NULL;
4306 }
Radek Krejci76512572015-08-04 09:47:08 +02004307 leaf->nodetype = LYS_LEAF;
4308 leaf->prev = (struct lys_node *)leaf;
4309 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004310
Radek Krejci07d0fb92017-01-13 14:11:05 +01004311 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4312 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 goto error;
4314 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004315
Radek Krejcia9544502015-08-14 08:24:29 +02004316 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004317
Radek Krejcic189a952016-07-11 15:27:07 +02004318 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004319 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004320 goto error;
4321 }
4322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004323 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004324 if (strcmp(sub->ns->value, LY_NSYIN)) {
4325 /* extension */
4326 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004327 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004328 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004329 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004330 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 goto error;
4332 }
Michal Vasko88c29542015-11-27 14:57:53 +01004333 /* HACK for unres */
4334 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004335 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004336 /* postpone type resolution when if-feature parsing is done since we need
4337 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004338 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004339 } else if (!strcmp(sub->name, "default")) {
4340 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004341 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 goto error;
4343 }
4344 GETVAL(value, sub, "value");
4345 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004346
4347 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4348 goto error;
4349 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350 } else if (!strcmp(sub->name, "units")) {
4351 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004352 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004353 goto error;
4354 }
4355 GETVAL(value, sub, "name");
4356 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004357
Radek Krejciac00b2a2017-01-17 14:05:00 +01004358 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004359 goto error;
4360 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004361 } else if (!strcmp(sub->name, "mandatory")) {
4362 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004363 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 goto error;
4365 }
4366 /* just checking the flags in leaf is not sufficient, we would allow
4367 * multiple mandatory statements with the "false" value
4368 */
4369 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 GETVAL(value, sub, "value");
4372 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004373 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004374 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004375 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004376 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004377 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 goto error;
4379 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004380
Radek Krejciac00b2a2017-01-17 14:05:00 +01004381 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004382 goto error;
4383 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004384 } else if (!strcmp(sub->name, "when")) {
4385 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004386 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004387 goto error;
4388 }
4389
Radek Krejci5323b492017-01-16 15:40:11 +01004390 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004391 if (!leaf->when) {
4392 goto error;
4393 }
4394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004396 c_must++;
4397 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004398 } else if (!strcmp(sub->name, "if-feature")) {
4399 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004403 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004406
Michal Vasko88c29542015-11-27 14:57:53 +01004407 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004411 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004412 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 goto error;
4414 }
Michal Vasko478c4652016-07-21 12:55:01 +02004415 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004416 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004417 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004418 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4419 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 /* middle part - process nodes with cardinality of 0..n */
4423 if (c_must) {
4424 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004425 if (!leaf->must) {
4426 LOGMEM;
4427 goto error;
4428 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004430 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004431 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4432 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004433 LOGMEM;
4434 goto error;
4435 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004436 }
Radek Krejcie534c132016-11-23 13:32:31 +01004437 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004438 /* some extensions may be already present from the substatements */
4439 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4440 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004441 LOGMEM;
4442 goto error;
4443 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004444 retval->ext = reallocated;
4445
4446 /* init memory */
4447 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004448 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004449
Radek Krejcie534c132016-11-23 13:32:31 +01004450 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4451 if (strcmp(sub->ns->value, LY_NSYIN)) {
4452 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004453 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 +01004454 retval->ext_size++;
4455 if (r) {
4456 goto error;
4457 }
4458 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004459 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004460 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 if (r) {
4462 goto error;
4463 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004464 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004465 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004466 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004467 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004468 goto error;
4469 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004472
Radek Krejcicbb473e2016-09-16 14:48:32 +02004473 /* finalize type parsing */
4474 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4475 leaf->type.der = NULL;
4476 goto error;
4477 }
4478
4479 /* check default value (if not defined, there still could be some restrictions
4480 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004481 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 +02004482 goto error;
4483 }
4484
Michal Vasko508a50d2016-09-07 14:50:33 +02004485 /* check XPath dependencies */
4486 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4487 goto error;
4488 }
4489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004490 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004491
4492error:
4493
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004494 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004497}
4498
Michal Vasko0d343d12015-08-24 14:57:36 +02004499/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004500static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004501read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004502 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004503{
Radek Krejci76512572015-08-04 09:47:08 +02004504 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004505 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 struct lyxml_elem *sub, *next;
4507 const char *value;
4508 char *endptr;
4509 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004510 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004511 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004513 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004516 if (!llist) {
4517 LOGMEM;
4518 return NULL;
4519 }
Radek Krejci76512572015-08-04 09:47:08 +02004520 llist->nodetype = LYS_LEAFLIST;
4521 llist->prev = (struct lys_node *)llist;
4522 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004523
Radek Krejci07d0fb92017-01-13 14:11:05 +01004524 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4525 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 goto error;
4527 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004528
Radek Krejcia9544502015-08-14 08:24:29 +02004529 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004530
Radek Krejcic189a952016-07-11 15:27:07 +02004531 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004532 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004533 goto error;
4534 }
4535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004537 if (strcmp(sub->ns->value, LY_NSYIN)) {
4538 /* extension */
4539 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004540 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004541 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004542 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004543 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 goto error;
4545 }
Michal Vasko88c29542015-11-27 14:57:53 +01004546 /* HACK for unres */
4547 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004548 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004549 /* postpone type resolution when if-feature parsing is done since we need
4550 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004551 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004552 } else if (!strcmp(sub->name, "units")) {
4553 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004554 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 goto error;
4556 }
4557 GETVAL(value, sub, "name");
4558 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004559
Radek Krejciac00b2a2017-01-17 14:05:00 +01004560 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004561 goto error;
4562 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 } else if (!strcmp(sub->name, "ordered-by")) {
4564 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004565 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 goto error;
4567 }
4568 /* just checking the flags in llist is not sufficient, we would
4569 * allow multiple ordered-by statements with the "system" value
4570 */
4571 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004572
Radek Krejci1574a8d2015-08-03 14:16:52 +02004573 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4575 * state data
4576 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004577 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 continue;
4579 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 GETVAL(value, sub, "value");
4582 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004583 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004585 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004587 } /* else system is the default value, so we can ignore it */
4588
Radek Krejciac00b2a2017-01-17 14:05:00 +01004589 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4590 goto error;
4591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 } else if (!strcmp(sub->name, "must")) {
4593 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004594 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004595 } else if (!strcmp(sub->name, "if-feature")) {
4596 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004598 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004599 /* read the default's extension instances */
4600 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
4601 goto error;
4602 }
4603
Radek Krejcid5a5c282016-08-15 15:38:08 +02004604 c_dflt++;
4605 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 } else if (!strcmp(sub->name, "min-elements")) {
4608 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004609 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 goto error;
4611 }
4612 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 GETVAL(value, sub, "value");
4615 while (isspace(value[0])) {
4616 value++;
4617 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 /* convert it to uint32_t */
4620 errno = 0;
4621 endptr = NULL;
4622 val = strtoul(value, &endptr, 10);
4623 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004624 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 goto error;
4626 }
4627 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004628 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004629 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004630 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004631 goto error;
4632 }
Radek Krejci5323b492017-01-16 15:40:11 +01004633
Radek Krejciac00b2a2017-01-17 14:05:00 +01004634 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004635 goto error;
4636 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004637 } else if (!strcmp(sub->name, "max-elements")) {
4638 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004639 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 goto error;
4641 }
4642 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 GETVAL(value, sub, "value");
4645 while (isspace(value[0])) {
4646 value++;
4647 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004648
Radek Krejci0d7b2472016-02-12 11:11:03 +01004649 if (!strcmp(value, "unbounded")) {
4650 llist->max = 0;
4651 } else {
4652 /* convert it to uint32_t */
4653 errno = 0;
4654 endptr = NULL;
4655 val = strtoul(value, &endptr, 10);
4656 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004657 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004658 goto error;
4659 }
4660 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004661 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004662 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004663 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004664 goto error;
4665 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004666 }
Radek Krejci5323b492017-01-16 15:40:11 +01004667
Radek Krejciac00b2a2017-01-17 14:05:00 +01004668 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004669 goto error;
4670 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004671 } else if (!strcmp(sub->name, "when")) {
4672 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004673 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004674 goto error;
4675 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004676
Radek Krejci5323b492017-01-16 15:40:11 +01004677 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004678 if (!llist->when) {
4679 goto error;
4680 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004682 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004685
Michal Vasko88c29542015-11-27 14:57:53 +01004686 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004687 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004690 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004691 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 goto error;
4693 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 /* middle part - process nodes with cardinality of 0..n */
4696 if (c_must) {
4697 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004698 if (!llist->must) {
4699 LOGMEM;
4700 goto error;
4701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004703 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004704 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4705 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004706 LOGMEM;
4707 goto error;
4708 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004709 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004710 if (c_dflt) {
4711 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4712 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004713 LOGMEM;
4714 goto error;
4715 }
4716 }
Radek Krejcie534c132016-11-23 13:32:31 +01004717 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004718 /* some extensions may be already present from the substatements */
4719 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4720 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004721 LOGMEM;
4722 goto error;
4723 }
Radek Krejci5323b492017-01-16 15:40:11 +01004724 retval->ext = reallocated;
4725
4726 /* init memory */
4727 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004728 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004729
Radek Krejcie534c132016-11-23 13:32:31 +01004730 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4731 if (strcmp(sub->ns->value, LY_NSYIN)) {
4732 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004733 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 +01004734 retval->ext_size++;
4735 if (r) {
4736 goto error;
4737 }
4738 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004739 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004740 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 if (r) {
4742 goto error;
4743 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004744 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004745 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004746 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004747 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004748 goto error;
4749 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004750 } else if (!strcmp(sub->name, "default")) {
4751 GETVAL(value, sub, "value");
4752
Radek Krejciac1a52c2016-09-15 14:42:40 +02004753 /* check for duplicity in case of configuration data,
4754 * in case of status data duplicities are allowed */
4755 if (llist->flags & LYS_CONFIG_W) {
4756 for (r = 0; r < llist->dflt_size; r++) {
4757 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004758 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004759 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004760 goto error;
4761 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004762 }
4763 }
4764 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004767
Radek Krejcicbb473e2016-09-16 14:48:32 +02004768 /* finalize type parsing */
4769 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4770 llist->type.der = NULL;
4771 goto error;
4772 }
4773
Radek Krejcid5a5c282016-08-15 15:38:08 +02004774 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004775 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004776 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004777 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4778 goto error;
4779 }
4780
4781 /* check default value (if not defined, there still could be some restrictions
4782 * that need to be checked against a default value from a derived type) */
4783 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004784 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4785 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004786 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004787 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004788 }
4789
Michal Vasko508a50d2016-09-07 14:50:33 +02004790 /* check XPath dependencies */
4791 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4792 goto error;
4793 }
4794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004795 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004796
4797error:
4798
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004799 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004802}
4803
Michal Vasko0d343d12015-08-24 14:57:36 +02004804/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004805static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004806read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004807 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004808{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004809 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004810 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004812 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004813 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004815 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 char *auxs;
4817 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004818 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004820 /* init */
4821 memset(&root, 0, sizeof root);
4822 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004825 if (!list) {
4826 LOGMEM;
4827 return NULL;
4828 }
Radek Krejci76512572015-08-04 09:47:08 +02004829 list->nodetype = LYS_LIST;
4830 list->prev = (struct lys_node *)list;
4831 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004832
Radek Krejci07d0fb92017-01-13 14:11:05 +01004833 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4834 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 goto error;
4836 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004837
Radek Krejcia9544502015-08-14 08:24:29 +02004838 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4839
Radek Krejcic189a952016-07-11 15:27:07 +02004840 /* insert the node into the schema tree */
4841 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4842 goto error;
4843 }
4844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 /* process list's specific children */
4846 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004847 if (strcmp(sub->ns->value, LY_NSYIN)) {
4848 /* extension */
4849 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004850 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004853 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 !strcmp(sub->name, "leaf-list") ||
4855 !strcmp(sub->name, "leaf") ||
4856 !strcmp(sub->name, "list") ||
4857 !strcmp(sub->name, "choice") ||
4858 !strcmp(sub->name, "uses") ||
4859 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004860 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004861 !strcmp(sub->name, "action") ||
4862 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004863 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004864 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 /* array counters */
4867 } else if (!strcmp(sub->name, "key")) {
4868 /* check cardinality 0..1 */
4869 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004870 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 goto error;
4872 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 /* count the number of keys */
4875 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004876 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 while ((value = strpbrk(value, " \t\n"))) {
4878 list->keys_size++;
4879 while (isspace(*value)) {
4880 value++;
4881 }
4882 }
4883 list->keys_size++;
4884 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004885 if (!list->keys) {
4886 LOGMEM;
4887 goto error;
4888 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004889
4890 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
4891 goto error;
4892 }
4893 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 } else if (!strcmp(sub->name, "unique")) {
4895 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004896 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004897 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 } else if (!strcmp(sub->name, "typedef")) {
4899 c_tpdf++;
4900 } else if (!strcmp(sub->name, "must")) {
4901 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004902 } else if (!strcmp(sub->name, "if-feature")) {
4903 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 /* optional stetments */
4906 } else if (!strcmp(sub->name, "ordered-by")) {
4907 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004908 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 goto error;
4910 }
4911 /* just checking the flags in llist is not sufficient, we would
4912 * allow multiple ordered-by statements with the "system" value
4913 */
4914 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004915
Radek Krejci1574a8d2015-08-03 14:16:52 +02004916 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4918 * state data
4919 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004920 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 continue;
4922 }
Radek Krejci345ad742015-06-03 11:04:18 +02004923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 GETVAL(value, sub, "value");
4925 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004926 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004927 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004928 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004930 } /* else system is the default value, so we can ignore it */
4931
4932 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4933 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004934 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004935 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 } else if (!strcmp(sub->name, "min-elements")) {
4937 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004938 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004939 goto error;
4940 }
4941 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004943 GETVAL(value, sub, "value");
4944 while (isspace(value[0])) {
4945 value++;
4946 }
Radek Krejci345ad742015-06-03 11:04:18 +02004947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004948 /* convert it to uint32_t */
4949 errno = 0;
4950 auxs = NULL;
4951 val = strtoul(value, &auxs, 10);
4952 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004953 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004954 goto error;
4955 }
4956 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004957 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004958 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004959 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004960 lyxml_free(module->ctx, sub);
4961 goto error;
4962 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004963 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
4964 goto error;
4965 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004966 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 } else if (!strcmp(sub->name, "max-elements")) {
4968 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004969 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004970 goto error;
4971 }
4972 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 GETVAL(value, sub, "value");
4975 while (isspace(value[0])) {
4976 value++;
4977 }
Radek Krejci345ad742015-06-03 11:04:18 +02004978
Radek Krejci0d7b2472016-02-12 11:11:03 +01004979 if (!strcmp(value, "unbounded")) {
4980 list->max = 0;;
4981 } else {
4982 /* convert it to uint32_t */
4983 errno = 0;
4984 auxs = NULL;
4985 val = strtoul(value, &auxs, 10);
4986 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004987 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004988 goto error;
4989 }
4990 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004991 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004992 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004993 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004994 goto error;
4995 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004996 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004997 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
4998 goto error;
4999 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005000 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005001 } else if (!strcmp(sub->name, "when")) {
5002 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005003 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005004 goto error;
5005 }
5006
Radek Krejci5323b492017-01-16 15:40:11 +01005007 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005008 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005009 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005010 goto error;
5011 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005012 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005013 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005014 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005015 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 }
5017 }
Radek Krejci345ad742015-06-03 11:04:18 +02005018
Michal Vaskoe022a562016-09-27 14:24:15 +02005019 /* check - if list is configuration, key statement is mandatory
5020 * (but only if we are not in a grouping or augment, then the check is deferred) */
5021 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005022 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005023 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005024 goto error;
5025 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5028 if (c_tpdf) {
5029 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005030 if (!list->tpdf) {
5031 LOGMEM;
5032 goto error;
5033 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005034 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005035 if (c_must) {
5036 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005037 if (!list->must) {
5038 LOGMEM;
5039 goto error;
5040 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005041 }
5042 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005043 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5044 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005045 LOGMEM;
5046 goto error;
5047 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005048 }
Radek Krejcie534c132016-11-23 13:32:31 +01005049 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005050 /* some extensions may be already present from the substatements */
5051 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5052 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005053 LOGMEM;
5054 goto error;
5055 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005056 retval->ext = reallocated;
5057
5058 /* init memory */
5059 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005060 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005061
Radek Krejcie534c132016-11-23 13:32:31 +01005062 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5063 if (strcmp(sub->ns->value, LY_NSYIN)) {
5064 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005065 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 +01005066 retval->ext_size++;
5067 if (r) {
5068 goto error;
5069 }
5070 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005071 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5072 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005073 if (r) {
5074 goto error;
5075 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005076 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005077 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005078 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005079 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005080 goto error;
5081 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005082 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005083 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005084 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005085 if (r) {
5086 goto error;
5087 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005088 }
5089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005091 /* last part - process data nodes */
5092 LY_TREE_FOR_SAFE(root.child, next, sub) {
5093 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005094 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005095 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005096 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005097 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005098 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005099 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005100 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005101 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005102 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005103 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005104 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005105 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005106 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005107 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005108 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005109 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005110 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005111 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005112 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005113 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005114 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005115 } else {
5116 LOGINT;
5117 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005118 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005119 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005120 goto error;
5121 }
Radek Krejci73adb602015-07-02 18:07:40 +02005122
Michal Vasko345da0a2015-12-02 10:35:55 +01005123 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005124 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005125
Radek Krejci5c08a992016-11-02 13:30:04 +01005126 if (list->keys_str) {
5127 /* check that we are not in grouping */
5128 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5129 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005130 goto error;
5131 }
5132 } /* 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 +02005133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 /* process unique statements */
5135 if (c_uniq) {
5136 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005137 if (!list->unique) {
5138 LOGMEM;
5139 goto error;
5140 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005141
Radek Krejci461efb92016-02-12 15:52:18 +01005142 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5143 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5144 list->unique_size++;
5145 if (r) {
5146 goto error;
5147 }
5148
Radek Krejcie36d7c72017-01-17 16:12:30 +01005149 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
5150 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5151 goto error;
5152 }
Radek Krejci461efb92016-02-12 15:52:18 +01005153 lyxml_free(module->ctx, sub);
5154 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005155 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005156
Michal Vasko508a50d2016-09-07 14:50:33 +02005157 /* check XPath dependencies */
5158 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5159 goto error;
5160 }
5161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005162 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005163
5164error:
5165
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005166 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005168 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 }
5170 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005171 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005174 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005175}
5176
Michal Vasko0d343d12015-08-24 14:57:36 +02005177/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005178static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005179read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005180 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005181{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005182 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005183 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005184 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005185 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005186 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005187 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005189 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005191 /* init */
5192 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005194 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005195 if (!cont) {
5196 LOGMEM;
5197 return NULL;
5198 }
Radek Krejci76512572015-08-04 09:47:08 +02005199 cont->nodetype = LYS_CONTAINER;
5200 cont->prev = (struct lys_node *)cont;
5201 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005202
Radek Krejci07d0fb92017-01-13 14:11:05 +01005203 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
5204 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 goto error;
5206 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005207
Radek Krejcia9544502015-08-14 08:24:29 +02005208 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5209
Radek Krejcic189a952016-07-11 15:27:07 +02005210 /* insert the node into the schema tree */
5211 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5212 goto error;
5213 }
5214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005215 /* process container's specific children */
5216 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005217 if (strcmp(sub->ns->value, LY_NSYIN)) {
5218 /* extension */
5219 c_ext++;
5220 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005221 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005222 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 goto error;
5224 }
5225 GETVAL(value, sub, "value");
5226 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005227
Radek Krejciac00b2a2017-01-17 14:05:00 +01005228 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005229 goto error;
5230 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005231 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005232 } else if (!strcmp(sub->name, "when")) {
5233 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005234 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005235 goto error;
5236 }
5237
Radek Krejci5323b492017-01-16 15:40:11 +01005238 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005239 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005240 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005241 goto error;
5242 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005243 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005245 /* data statements */
5246 } else if (!strcmp(sub->name, "container") ||
5247 !strcmp(sub->name, "leaf-list") ||
5248 !strcmp(sub->name, "leaf") ||
5249 !strcmp(sub->name, "list") ||
5250 !strcmp(sub->name, "choice") ||
5251 !strcmp(sub->name, "uses") ||
5252 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005253 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005254 !strcmp(sub->name, "action") ||
5255 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005256 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005257 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 /* array counters */
5260 } else if (!strcmp(sub->name, "typedef")) {
5261 c_tpdf++;
5262 } else if (!strcmp(sub->name, "must")) {
5263 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005264 } else if (!strcmp(sub->name, "if-feature")) {
5265 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005266 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005267 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 }
5270 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5273 if (c_tpdf) {
5274 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005275 if (!cont->tpdf) {
5276 LOGMEM;
5277 goto error;
5278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 }
5280 if (c_must) {
5281 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005282 if (!cont->must) {
5283 LOGMEM;
5284 goto error;
5285 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005287 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005288 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5289 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005290 LOGMEM;
5291 goto error;
5292 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005293 }
Radek Krejcie534c132016-11-23 13:32:31 +01005294 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005295 /* some extensions may be already present from the substatements */
5296 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5297 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005298 LOGMEM;
5299 goto error;
5300 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005301 retval->ext = reallocated;
5302
5303 /* init memory */
5304 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005305 }
Radek Krejci800af702015-06-02 13:46:01 +02005306
Radek Krejcie534c132016-11-23 13:32:31 +01005307 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5308 if (strcmp(sub->ns->value, LY_NSYIN)) {
5309 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005310 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 +01005311 retval->ext_size++;
5312 if (r) {
5313 goto error;
5314 }
5315 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005316 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5317 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 if (r) {
5319 goto error;
5320 }
5321 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005322 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005323 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005324 if (r) {
5325 goto error;
5326 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005327 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005328 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005329 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005330 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005331 goto error;
5332 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005336 /* last part - process data nodes */
5337 LY_TREE_FOR_SAFE(root.child, next, sub) {
5338 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005339 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005341 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005343 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005345 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005347 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005348 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005349 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005351 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005352 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005353 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005354 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005355 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005356 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005357 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005358 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005359 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005361 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005362 goto error;
5363 }
Radek Krejci73adb602015-07-02 18:07:40 +02005364
Michal Vasko345da0a2015-12-02 10:35:55 +01005365 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005367
Michal Vasko508a50d2016-09-07 14:50:33 +02005368 /* check XPath dependencies */
5369 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5370 goto error;
5371 }
5372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005373 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005374
5375error:
5376
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005377 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005378 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005379 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005380 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005382 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005383}
5384
Michal Vasko0d343d12015-08-24 14:57:36 +02005385/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005386static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005387read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005388 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005389{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005390 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005391 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005392 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005393 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005394 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005395 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005396 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005398 /* init */
5399 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005401 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005402 if (!grp) {
5403 LOGMEM;
5404 return NULL;
5405 }
Radek Krejci76512572015-08-04 09:47:08 +02005406 grp->nodetype = LYS_GROUPING;
5407 grp->prev = (struct lys_node *)grp;
5408 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005409
Radek Krejci07d0fb92017-01-13 14:11:05 +01005410 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005411 goto error;
5412 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005413
Radek Krejcia9544502015-08-14 08:24:29 +02005414 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5415
Radek Krejcic189a952016-07-11 15:27:07 +02005416 /* insert the node into the schema tree */
5417 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5418 goto error;
5419 }
5420
Radek Krejci1d82ef62015-08-07 14:44:40 +02005421 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005422 if (strcmp(sub->ns->value, LY_NSYIN)) {
5423 /* extension */
5424 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005426 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005427 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005428 !strcmp(sub->name, "leaf-list") ||
5429 !strcmp(sub->name, "leaf") ||
5430 !strcmp(sub->name, "list") ||
5431 !strcmp(sub->name, "choice") ||
5432 !strcmp(sub->name, "uses") ||
5433 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005434 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005435 !strcmp(sub->name, "action") ||
5436 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005437 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005438 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005440 /* array counters */
5441 } else if (!strcmp(sub->name, "typedef")) {
5442 c_tpdf++;
5443 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005444 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005445 goto error;
5446 }
5447 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005449 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5450 if (c_tpdf) {
5451 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005452 if (!grp->tpdf) {
5453 LOGMEM;
5454 goto error;
5455 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005456 }
Radek Krejcie534c132016-11-23 13:32:31 +01005457 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005458 /* some extensions may be already present from the substatements */
5459 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5460 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005461 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005462 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005463 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005464 retval->ext = reallocated;
5465
5466 /* init memory */
5467 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005468 }
Radek Krejcie534c132016-11-23 13:32:31 +01005469 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5470 if (strcmp(sub->ns->value, LY_NSYIN)) {
5471 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005472 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 +01005473 retval->ext_size++;
5474 if (r) {
5475 goto error;
5476 }
5477 } else {
5478 /* typedef */
5479 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5480 grp->tpdf_size++;
5481 if (r) {
5482 goto error;
5483 }
5484 }
5485 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005487 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005488 if (!root.child) {
5489 LOGWRN("Grouping \"%s\" without children.", retval->name);
5490 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005491 LY_TREE_FOR_SAFE(root.child, next, sub) {
5492 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005493 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005494 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005495 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005496 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005497 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005498 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005499 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005500 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005501 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005502 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005503 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005504 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005505 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005506 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005507 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005508 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005509 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005510 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005511 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005512 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005513 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005514 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005515 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005516 goto error;
5517 }
Radek Krejci73adb602015-07-02 18:07:40 +02005518
Michal Vasko345da0a2015-12-02 10:35:55 +01005519 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005520 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005522 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005523
5524error:
5525
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005526 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005527 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005528 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005531 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005532}
5533
Michal Vasko0d343d12015-08-24 14:57:36 +02005534/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005535static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005536read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005537 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005538{
Radek Krejcie0674f82015-06-15 13:58:51 +02005539 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005540 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005541 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005542 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005543 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005544 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005545
Radek Krejcie0674f82015-06-15 13:58:51 +02005546 /* init */
5547 memset(&root, 0, sizeof root);
5548
Michal Vasko38d01f72015-06-15 09:41:06 +02005549 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005550 if (!inout) {
5551 LOGMEM;
5552 return NULL;
5553 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005554 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005555
5556 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005557 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005558 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005559 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005560 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005561 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005562 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005563 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005564 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005565 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005566 }
5567
Radek Krejci76512572015-08-04 09:47:08 +02005568 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005569 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005570
Radek Krejcia9544502015-08-14 08:24:29 +02005571 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5572
Radek Krejcic189a952016-07-11 15:27:07 +02005573 /* insert the node into the schema tree */
5574 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5575 goto error;
5576 }
5577
Michal Vasko38d01f72015-06-15 09:41:06 +02005578 /* data statements */
5579 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005580 if (!sub->ns) {
5581 /* garbage */
5582 lyxml_free(module->ctx, sub);
5583 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005584 /* extension */
5585 c_ext++;
5586 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005587 !strcmp(sub->name, "leaf-list") ||
5588 !strcmp(sub->name, "leaf") ||
5589 !strcmp(sub->name, "list") ||
5590 !strcmp(sub->name, "choice") ||
5591 !strcmp(sub->name, "uses") ||
5592 !strcmp(sub->name, "grouping") ||
5593 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005594 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005595 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005597 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005598 } else if (!strcmp(sub->name, "typedef")) {
5599 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005600
Radek Krejci1a31efe2016-07-29 11:04:16 +02005601 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005602 c_must++;
5603
Michal Vasko38d01f72015-06-15 09:41:06 +02005604 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005605 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005606 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005607 }
5608 }
5609
5610 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5611 if (c_tpdf) {
5612 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005613 if (!inout->tpdf) {
5614 LOGMEM;
5615 goto error;
5616 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005617 }
Radek Krejci19332802016-07-29 10:39:46 +02005618 if (c_must) {
5619 inout->must = calloc(c_must, sizeof *inout->must);
5620 if (!inout->must) {
5621 LOGMEM;
5622 goto error;
5623 }
5624 }
Radek Krejcie534c132016-11-23 13:32:31 +01005625 if (c_ext) {
5626 inout->ext = calloc(c_ext, sizeof *inout->ext);
5627 if (!inout->ext) {
5628 LOGMEM;
5629 goto error;
5630 }
5631 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005632
Radek Krejcie534c132016-11-23 13:32:31 +01005633 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5634 if (strcmp(sub->ns->value, LY_NSYIN)) {
5635 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005636 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 +01005637 retval->ext_size++;
5638 if (r) {
5639 goto error;
5640 }
5641 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005642 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005643 inout->must_size++;
5644 if (r) {
5645 goto error;
5646 }
5647 } else { /* typedef */
5648 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5649 inout->tpdf_size++;
5650 if (r) {
5651 goto error;
5652 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005653 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005654 }
5655
5656 /* last part - process data nodes */
5657 LY_TREE_FOR_SAFE(root.child, next, sub) {
5658 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005659 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005660 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005661 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005662 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005663 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005664 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005665 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005666 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005667 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005668 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005669 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005670 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005671 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005672 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005673 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005674 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005675 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005676 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005677 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005678 goto error;
5679 }
Radek Krejci73adb602015-07-02 18:07:40 +02005680
Michal Vasko345da0a2015-12-02 10:35:55 +01005681 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005682 }
5683
Michal Vasko508a50d2016-09-07 14:50:33 +02005684 /* check XPath dependencies */
5685 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5686 goto error;
5687 }
5688
Michal Vasko38d01f72015-06-15 09:41:06 +02005689 return retval;
5690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005691error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005692
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005693 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005694 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005695 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005696 }
5697
5698 return NULL;
5699}
5700
Michal Vasko0d343d12015-08-24 14:57:36 +02005701/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005702static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005703read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005704 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005705{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005706 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005707 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005708 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005709 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005710 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005711 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02005712
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005713 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005714 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005715 return NULL;
5716 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005717
Michal Vaskoc6551b32015-06-16 10:51:43 +02005718 memset(&root, 0, sizeof root);
5719
Michal Vasko0ea41032015-06-16 08:53:55 +02005720 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005721 if (!notif) {
5722 LOGMEM;
5723 return NULL;
5724 }
Radek Krejci76512572015-08-04 09:47:08 +02005725 notif->nodetype = LYS_NOTIF;
5726 notif->prev = (struct lys_node *)notif;
5727 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005728
Radek Krejci07d0fb92017-01-13 14:11:05 +01005729 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005730 goto error;
5731 }
5732
Radek Krejcia9544502015-08-14 08:24:29 +02005733 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5734
Radek Krejcic189a952016-07-11 15:27:07 +02005735 /* insert the node into the schema tree */
5736 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5737 goto error;
5738 }
5739
Michal Vasko0ea41032015-06-16 08:53:55 +02005740 /* process rpc's specific children */
5741 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005742 if (strcmp(sub->ns->value, LY_NSYIN)) {
5743 /* extension */
5744 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005745 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005746
Michal Vasko0ea41032015-06-16 08:53:55 +02005747 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005748 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749 !strcmp(sub->name, "leaf-list") ||
5750 !strcmp(sub->name, "leaf") ||
5751 !strcmp(sub->name, "list") ||
5752 !strcmp(sub->name, "choice") ||
5753 !strcmp(sub->name, "uses") ||
5754 !strcmp(sub->name, "grouping") ||
5755 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005756 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005757 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005759 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005760 } else if (!strcmp(sub->name, "typedef")) {
5761 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005762 } else if (!strcmp(sub->name, "if-feature")) {
5763 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005764 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005765 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005766 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005767 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005768 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005769 }
5770 }
5771
5772 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5773 if (c_tpdf) {
5774 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005775 if (!notif->tpdf) {
5776 LOGMEM;
5777 goto error;
5778 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005779 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005780 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005781 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5782 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005783 LOGMEM;
5784 goto error;
5785 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005786 }
Radek Krejci19332802016-07-29 10:39:46 +02005787 if (c_must) {
5788 notif->must = calloc(c_must, sizeof *notif->must);
5789 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005790 LOGMEM;
5791 goto error;
5792 }
5793 }
Radek Krejcie534c132016-11-23 13:32:31 +01005794 if (c_ext) {
5795 notif->ext = calloc(c_ext, sizeof *notif->ext);
5796 if (!notif->ext) {
5797 LOGMEM;
5798 goto error;
5799 }
5800 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005801
Radek Krejcie534c132016-11-23 13:32:31 +01005802 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5803 if (strcmp(sub->ns->value, LY_NSYIN)) {
5804 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005805 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 +01005806 retval->ext_size++;
5807 if (r) {
5808 goto error;
5809 }
5810 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005811 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5812 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005813 if (r) {
5814 goto error;
5815 }
Radek Krejci96299152016-06-22 10:17:50 +02005816 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005817 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005818 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005819 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005820 goto error;
5821 }
Radek Krejci19332802016-07-29 10:39:46 +02005822 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005823 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005824 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005825 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005826 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005827 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005828 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005829 }
5830
5831 /* last part - process data nodes */
5832 LY_TREE_FOR_SAFE(root.child, next, sub) {
5833 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005834 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005835 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005836 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005837 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005838 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005839 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005840 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005841 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005842 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005843 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005844 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005845 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005846 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005847 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005848 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005849 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005850 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005851 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005852 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005853 goto error;
5854 }
Radek Krejci73adb602015-07-02 18:07:40 +02005855
Michal Vasko345da0a2015-12-02 10:35:55 +01005856 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005857 }
5858
Michal Vasko508a50d2016-09-07 14:50:33 +02005859 /* check XPath dependencies */
5860 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5861 goto error;
5862 }
5863
Michal Vasko0ea41032015-06-16 08:53:55 +02005864 return retval;
5865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005866error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005867
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005868 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005869 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005870 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005871 }
5872
5873 return NULL;
5874}
5875
Michal Vasko0d343d12015-08-24 14:57:36 +02005876/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005877static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005878read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005879 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005880{
Radek Krejcie0674f82015-06-15 13:58:51 +02005881 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005882 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005883 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005884 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005885 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005886 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005887
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005888 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005889 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005890 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005891 return NULL;
5892 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005893 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005894 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005895 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005896 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005897 return NULL;
5898 }
5899 }
5900 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005901
Radek Krejcie0674f82015-06-15 13:58:51 +02005902 /* init */
5903 memset(&root, 0, sizeof root);
5904
Michal Vasko38d01f72015-06-15 09:41:06 +02005905 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005906 if (!rpc) {
5907 LOGMEM;
5908 return NULL;
5909 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005910 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005911 rpc->prev = (struct lys_node *)rpc;
5912 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005913
Radek Krejci07d0fb92017-01-13 14:11:05 +01005914 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005915 goto error;
5916 }
5917
Radek Krejcia9544502015-08-14 08:24:29 +02005918 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5919
Radek Krejcic189a952016-07-11 15:27:07 +02005920 /* insert the node into the schema tree */
5921 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5922 goto error;
5923 }
5924
Michal Vasko38d01f72015-06-15 09:41:06 +02005925 /* process rpc's specific children */
5926 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005927 if (strcmp(sub->ns->value, LY_NSYIN)) {
5928 /* extension */
5929 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005930 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005931 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005932 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005933 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005934 goto error;
5935 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005936 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005937 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005938 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005939 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005940 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005941 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005942 goto error;
5943 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005944 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005945 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005946 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005948 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005949 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005950 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005951 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005953 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005954 } else if (!strcmp(sub->name, "typedef")) {
5955 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005956 } else if (!strcmp(sub->name, "if-feature")) {
5957 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005958 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005959 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005960 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005961 }
5962 }
5963
5964 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5965 if (c_tpdf) {
5966 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005967 if (!rpc->tpdf) {
5968 LOGMEM;
5969 goto error;
5970 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005971 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005972 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005973 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5974 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005975 LOGMEM;
5976 goto error;
5977 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005978 }
Radek Krejcie534c132016-11-23 13:32:31 +01005979 if (c_ext) {
5980 rpc->ext = calloc(c_ext, sizeof *rpc->ext);
5981 if (!rpc->ext) {
5982 LOGMEM;
5983 goto error;
5984 }
5985 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005986
Radek Krejcie534c132016-11-23 13:32:31 +01005987 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5988 if (strcmp(sub->ns->value, LY_NSYIN)) {
5989 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005990 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 +01005991 retval->ext_size++;
5992 if (r) {
5993 goto error;
5994 }
5995 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005996 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5997 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005998 if (r) {
5999 goto error;
6000 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006001 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006002 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006003 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006004 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006005 goto error;
6006 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006007 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006008 }
6009
6010 /* last part - process data nodes */
6011 LY_TREE_FOR_SAFE(root.child, next, sub) {
6012 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006013 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006014 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006015 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006016 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006017 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006018 goto error;
6019 }
Radek Krejci73adb602015-07-02 18:07:40 +02006020
Michal Vasko345da0a2015-12-02 10:35:55 +01006021 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006022 }
6023
Michal Vasko38d01f72015-06-15 09:41:06 +02006024 return retval;
6025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006026error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006027
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006028 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006029 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006030 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006031 }
6032
6033 return NULL;
6034}
6035
Michal Vasko0d343d12015-08-24 14:57:36 +02006036/* logs directly
6037 *
Radek Krejci74705112015-06-05 10:25:44 +02006038 * resolve - referenced grouping should be bounded to the namespace (resolved)
6039 * only when uses does not appear in grouping. In a case of grouping's uses,
6040 * we just get information but we do not apply augment or refine to it.
6041 */
Radek Krejci76512572015-08-04 09:47:08 +02006042static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02006043read_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 +02006044{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006045 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006046 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006047 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006048 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006049 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006050 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006051 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006053 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006054 if (!uses) {
6055 LOGMEM;
6056 return NULL;
6057 }
Radek Krejci76512572015-08-04 09:47:08 +02006058 uses->nodetype = LYS_USES;
6059 uses->prev = (struct lys_node *)uses;
6060 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006061
Radek Krejcia9544502015-08-14 08:24:29 +02006062 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006063 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006064
Radek Krejci07d0fb92017-01-13 14:11:05 +01006065 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006066 goto error;
6067 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006068
Radek Krejcia9544502015-08-14 08:24:29 +02006069 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6070
Radek Krejcic189a952016-07-11 15:27:07 +02006071 /* insert the node into the schema tree */
6072 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6073 goto error;
6074 }
6075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006076 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006077 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006078 if (strcmp(sub->ns->value, LY_NSYIN)) {
6079 /* extension */
6080 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006081 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006082 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006083 c_ref++;
6084 } else if (!strcmp(sub->name, "augment")) {
6085 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006086 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006087 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006088 } else if (!strcmp(sub->name, "when")) {
6089 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006090 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006091 goto error;
6092 }
6093
Radek Krejci5323b492017-01-16 15:40:11 +01006094 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006095 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006096 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006097 goto error;
6098 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006099 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006100 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006101 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006102 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006103 }
6104 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006106 /* process properties with cardinality 0..n */
6107 if (c_ref) {
6108 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006109 if (!uses->refine) {
6110 LOGMEM;
6111 goto error;
6112 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006113 }
6114 if (c_aug) {
6115 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006116 if (!uses->augment) {
6117 LOGMEM;
6118 goto error;
6119 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006120 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006121 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006122 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6123 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006124 LOGMEM;
6125 goto error;
6126 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006127 }
Radek Krejcie534c132016-11-23 13:32:31 +01006128 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006129 /* some extensions may be already present from the substatements */
6130 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6131 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006132 LOGMEM;
6133 goto error;
6134 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006135 retval->ext = reallocated;
6136
6137 /* init memory */
6138 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006139 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006140
Radek Krejcie534c132016-11-23 13:32:31 +01006141 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6142 if (strcmp(sub->ns->value, LY_NSYIN)) {
6143 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006144 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 +01006145 retval->ext_size++;
6146 if (r) {
6147 goto error;
6148 }
6149 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006150 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006151 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006152 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006153 goto error;
6154 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006155 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006156 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
6157 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006158 if (r) {
6159 goto error;
6160 }
6161 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006162 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006163 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006164 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006165 goto error;
6166 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006167 }
6168 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006169
Radek Krejci48464ed2016-03-17 15:44:09 +01006170 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006171 goto error;
6172 }
Radek Krejci74705112015-06-05 10:25:44 +02006173
Michal Vasko508a50d2016-09-07 14:50:33 +02006174 /* check XPath dependencies */
6175 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
6176 goto error;
6177 }
6178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006179 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006180
6181error:
6182
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006183 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006185 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006186}
6187
Michal Vasko0d343d12015-08-24 14:57:36 +02006188/* logs directly
6189 *
6190 * common code for yin_read_module() and yin_read_submodule()
6191 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006192static int
Radek Krejcic071c542016-01-27 14:57:51 +01006193read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6194 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006195{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006196 struct ly_ctx *ctx = module->ctx;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006197 struct lyxml_elem *next, *child, *next2, *child2, root, grps, augs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006198 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006199 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006200 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01006201 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01006202 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006203 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006204 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;
6205 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006206 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006207
Radek Krejcic071c542016-01-27 14:57:51 +01006208 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006209 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006211 /* init */
6212 memset(&root, 0, sizeof root);
6213 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006214 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006215 memset(&exts, 0, sizeof exts);
Radek Krejcie0674f82015-06-15 13:58:51 +02006216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006217 /*
6218 * in the first run, we process elements with cardinality of 1 or 0..1 and
6219 * count elements with cardinality 0..n. Data elements (choices, containers,
6220 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6221 * need have all top-level and groupings already prepared at that time. In
6222 * the middle loop, we process other elements with carinality of 0..n since
6223 * we need to allocate arrays to store them.
6224 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006225 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006226 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006227 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006228 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006229 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006230 } else if (strcmp(child->ns->value, LY_NSYIN)) {
6231 /* possible extension instance */
6232 lyxml_unlink_elem(module->ctx, child, 2);
6233 lyxml_add_child(module->ctx, &exts, child);
6234 c_extinst++;
6235 } else if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006236 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006237 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006238 goto error;
6239 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006240 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006241 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006242
6243 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
6244 goto error;
6245 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006246 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006247 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006248 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006249 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006250 goto error;
6251 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006252 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01006253 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006254 goto error;
6255 }
6256 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006257
6258 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
6259 goto error;
6260 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006261 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006262 } else if (submodule && !strcmp(child->name, "belongs-to")) {
6263 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006264 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006265 goto error;
6266 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006267 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006268 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006269 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006270 goto error;
6271 }
Radek Krejcif3886932015-06-04 17:36:06 +02006272
Radek Krejci95f22ae2017-01-20 14:25:53 +01006273 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
6274 goto error;
6275 }
6276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006277 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006278 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006279 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006280 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006281 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006282 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006283 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006284 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006285 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006286 goto error;
6287 }
6288 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006289 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006290 /* check here differs from a generic prefix check, since this prefix
6291 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006292 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006293 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006294 goto error;
6295 }
Radek Krejcic071c542016-01-27 14:57:51 +01006296 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006297
Radek Krejci95f22ae2017-01-20 14:25:53 +01006298 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
6299 goto error;
6300 }
6301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006302 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006303 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006304
6305 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006306 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006307 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006308 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006309 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006310 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006311 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006312 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006313 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006314 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006315 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006316 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006317 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006318 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006319 lyxml_unlink_elem(ctx, child, 2);
6320 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006321
Radek Krejci1d82ef62015-08-07 14:44:40 +02006322 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006323 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006325 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006326 } else if (!strcmp(child->name, "container") ||
6327 !strcmp(child->name, "leaf-list") ||
6328 !strcmp(child->name, "leaf") ||
6329 !strcmp(child->name, "list") ||
6330 !strcmp(child->name, "choice") ||
6331 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006332 !strcmp(child->name, "anyxml") ||
6333 !strcmp(child->name, "rpc") ||
6334 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006335 lyxml_unlink_elem(ctx, child, 2);
6336 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006337
Radek Krejci1d82ef62015-08-07 14:44:40 +02006338 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006339 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006340 lyxml_unlink_elem(ctx, child, 2);
6341 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006343 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006344 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006345 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006346 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006347 goto error;
6348 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006349 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6350 goto error;
6351 }
Radek Krejcic071c542016-01-27 14:57:51 +01006352 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006353 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006354 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006355 goto error;
6356 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006357 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006358 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006359 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006360 goto error;
6361 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006362 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6363 goto error;
6364 }
Radek Krejcic071c542016-01-27 14:57:51 +01006365 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006366 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006367 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006368 goto error;
6369 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006370 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006371 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006372 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006373 goto error;
6374 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006375 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
6376 goto error;
6377 }
Radek Krejcic071c542016-01-27 14:57:51 +01006378 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006379 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006380 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006381 goto error;
6382 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006383 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006384 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006385 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006386 goto error;
6387 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006388 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
6389 goto error;
6390 }
Radek Krejcic071c542016-01-27 14:57:51 +01006391 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006392 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006393 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006394 goto error;
6395 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006396 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006397 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006398 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006399 goto error;
6400 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006401 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006402 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006403 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006404 goto error;
6405 }
Radek Krejcic071c542016-01-27 14:57:51 +01006406 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006407 if (!strcmp(value, "1")) {
6408 if (submodule) {
6409 if (module->version > 1) {
6410 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6411 goto error;
6412 }
6413 } else {
6414 module->version = 1;
6415 }
6416 } else {
6417 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006418 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006419 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6420 goto error;
6421 }
6422 } else {
6423 module->version = 2;
6424 }
6425 }
6426
Radek Krejci95f22ae2017-01-20 14:25:53 +01006427 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
6428 goto error;
6429 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006430 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006431
Radek Krejci1d82ef62015-08-07 14:44:40 +02006432 } else if (!strcmp(child->name, "extension")) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09006433 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006434
Radek Krejcia1a6b762016-11-14 09:53:38 +09006435 } else if (!strcmp(child->name, "deviation")) {
6436 c_dev++;
6437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006438 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006439 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006440 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006441 }
6442 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006443
Radek Krejcic071c542016-01-27 14:57:51 +01006444 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006445 if (submodule) {
6446 if (!submodule->prefix) {
6447 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6448 goto error;
6449 }
6450 if (!version_flag) {
6451 /* check version compatibility with the main module */
6452 if (module->version > 1) {
6453 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6454 goto error;
6455 }
6456 }
6457 } else {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006458 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006459 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006460 goto error;
6461 }
6462 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006463 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006464 goto error;
6465 }
6466 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006468 /* allocate arrays for elements with cardinality of 0..n */
6469 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006470 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006471 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006472 LOGMEM;
6473 goto error;
6474 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006475 }
6476 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006477 trg->rev = calloc(c_rev, sizeof *trg->rev);
6478 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006479 LOGMEM;
6480 goto error;
6481 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006482 }
6483 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006484 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6485 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006486 LOGMEM;
6487 goto error;
6488 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006489 }
6490 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006491 trg->ident = calloc(c_ident, sizeof *trg->ident);
6492 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006493 LOGMEM;
6494 goto error;
6495 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006496 }
6497 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006498 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006499 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006500 LOGMEM;
6501 goto error;
6502 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006503 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006504 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006505 trg->augment = calloc(c_aug, sizeof *trg->augment);
6506 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006507 LOGMEM;
6508 goto error;
6509 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006510 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006511 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006512 trg->features = calloc(c_ftrs, sizeof *trg->features);
6513 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006514 LOGMEM;
6515 goto error;
6516 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006517 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006518 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006519 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6520 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006521 LOGMEM;
6522 goto error;
6523 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006524 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006525 if (c_ext) {
6526 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6527 if (!trg->extensions) {
6528 LOGMEM;
6529 goto error;
6530 }
6531 }
Radek Krejcie534c132016-11-23 13:32:31 +01006532 if (c_extinst) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006533 /* some extensions may be already present from the substatements */
6534 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
6535 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006536 LOGMEM;
6537 goto error;
6538 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006539 trg->ext = reallocated;
6540
6541 /* init memory */
6542 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006543 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006544
Michal Vasko2f7925f2015-10-21 15:06:56 +02006545 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
6546 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006547 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006548 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006549 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006550 if (r) {
6551 goto error;
6552 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006553
Radek Krejci1d82ef62015-08-07 14:44:40 +02006554 } else if (!strcmp(child->name, "include")) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006555 r = fill_yin_include(trg, submodule, child, &trg->inc[trg->inc_size], unres);
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006556 trg->inc_size++;
6557 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006558 goto error;
6559 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006560
Radek Krejci1d82ef62015-08-07 14:44:40 +02006561 } else if (!strcmp(child->name, "revision")) {
6562 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01006563 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006564 goto error;
6565 }
Radek Krejcic071c542016-01-27 14:57:51 +01006566 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006567 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01006568 for (i = 0; i < trg->rev_size; i++) {
6569 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006570 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
6571 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006572 }
6573 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006574
Radek Krejci95f22ae2017-01-20 14:25:53 +01006575 LY_TREE_FOR_SAFE(child->child, next2, child2) {
6576 if (!child2->ns) {
6577 /* garbage */
6578 continue;
6579 } else if (strcmp(child2->ns->value, LY_NSYIN)) {
6580 /* possible extension instance */
6581 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6582 child2, LYEXT_SUBSTMT_SELF, 0, unres)) {
6583 goto error;
6584 }
6585 } else if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006586 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006587 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006588 goto error;
6589 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006590 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6591 child2, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6592 goto error;
6593 }
Radek Krejcic071c542016-01-27 14:57:51 +01006594 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
6595 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006596 goto error;
6597 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006598 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006599 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006600 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006601 goto error;
6602 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006603 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6604 child2, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6605 goto error;
6606 }
Radek Krejcic071c542016-01-27 14:57:51 +01006607 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
6608 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006609 goto error;
6610 }
6611 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006612 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006613 goto error;
6614 }
6615 }
Radek Krejcic071c542016-01-27 14:57:51 +01006616 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006617
Radek Krejci1d82ef62015-08-07 14:44:40 +02006618 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006619 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6620 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006621 if (r) {
6622 goto error;
6623 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006624
Radek Krejci1d82ef62015-08-07 14:44:40 +02006625 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006626 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6627 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006628 if (r) {
6629 goto error;
6630 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006631
Radek Krejci1d82ef62015-08-07 14:44:40 +02006632 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006633 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6634 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006635 if (r) {
6636 goto error;
6637 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006638
Radek Krejcia1a6b762016-11-14 09:53:38 +09006639 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006640 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006641 trg->extensions_size++;
6642 if (r) {
6643 goto error;
6644 }
6645
Radek Krejci1d82ef62015-08-07 14:44:40 +02006646 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006647 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6648 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006649 if (r) {
6650 goto error;
6651 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006652 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006653 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006654
Radek Krejcie534c132016-11-23 13:32:31 +01006655 /* process extension instances */
6656 LY_TREE_FOR_SAFE(exts.child, next, child) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006657 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 +01006658 trg->ext_size++;
6659 if (r) {
6660 goto error;
6661 }
6662 }
6663
Radek Krejcif5be10f2015-06-16 13:29:36 +02006664 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006665 * refer to them. Submodule's data nodes are stored in the
6666 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006667 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006668 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006669 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006670 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006671 goto error;
6672 }
Radek Krejci74705112015-06-05 10:25:44 +02006673
Michal Vasko345da0a2015-12-02 10:35:55 +01006674 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006675 }
Radek Krejci74705112015-06-05 10:25:44 +02006676
Radek Krejcif5be10f2015-06-16 13:29:36 +02006677 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006678 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006679
Radek Krejci1d82ef62015-08-07 14:44:40 +02006680 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006681 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006682 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006683 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006684 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006685 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006686 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006687 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006688 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006689 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006690 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006691 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006692 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02006693 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
6694 } else if (!strcmp(child->name, "anydata")) {
6695 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006696 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006697 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006698 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006699 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006700 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006701 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006702 goto error;
6703 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006704
Michal Vasko345da0a2015-12-02 10:35:55 +01006705 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006706 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006707
Michal Vasko2f7925f2015-10-21 15:06:56 +02006708 /* ... and finally augments (last, so we can augment our data, for instance) */
6709 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01006710 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
6711 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006712
Michal Vasko2f7925f2015-10-21 15:06:56 +02006713 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006714 goto error;
6715 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006716 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006717 }
6718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006719 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02006720
6721error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006722 /* cleanup */
6723 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006724 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006725 }
6726 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006727 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006728 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006729 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006730 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006731 }
Radek Krejcie534c132016-11-23 13:32:31 +01006732 while (exts.child) {
6733 lyxml_free(module->ctx, exts.child);
6734 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006736 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02006737}
6738
Michal Vasko0d343d12015-08-24 14:57:36 +02006739/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006740struct lys_submodule *
6741yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02006742{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006743 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006744 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006745 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006746
Michal Vasko5a721fd2016-02-16 12:16:48 +01006747 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006748
Radek Krejci722b0072016-02-01 17:09:45 +01006749 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006750 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01006751 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006752 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006754 /* check root element */
6755 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006756 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006757 goto error;
6758 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006760 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006761 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006762 goto error;
6763 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006764
Michal Vasko5a721fd2016-02-16 12:16:48 +01006765 submodule = calloc(1, sizeof *submodule);
6766 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006767 LOGMEM;
6768 goto error;
6769 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006770
Michal Vasko5a721fd2016-02-16 12:16:48 +01006771 submodule->ctx = module->ctx;
6772 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
6773 submodule->type = 1;
6774 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02006775
Michal Vasko5a721fd2016-02-16 12:16:48 +01006776 LOGVRB("Reading submodule \"%s\".", submodule->name);
6777 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006778 goto error;
6779 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006780
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006781 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01006782 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02006783
Michal Vasko5a721fd2016-02-16 12:16:48 +01006784 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006785 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02006786
6787error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006788 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006789 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01006790 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01006791
Michal Vasko5a721fd2016-02-16 12:16:48 +01006792 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01006793 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01006794 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01006795 }
6796
Michal Vasko5a721fd2016-02-16 12:16:48 +01006797 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01006798
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006799 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6800 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006801 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006802 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006803}
6804
Michal Vasko0d343d12015-08-24 14:57:36 +02006805/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006806struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01006807yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006808{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006809 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006810 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006811 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006812 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006813
Radek Krejcic071c542016-01-27 14:57:51 +01006814 unres = calloc(1, sizeof *unres);
6815 if (!unres) {
6816 LOGMEM;
6817 return NULL;
6818 }
6819
Radek Krejci722b0072016-02-01 17:09:45 +01006820 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006821 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01006822 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006823 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006825 /* check root element */
6826 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02006827 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006828 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
6829 } else {
6830 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02006831 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006832 goto error;
6833 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006835 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006836 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006837 goto error;
6838 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006840 module = calloc(1, sizeof *module);
6841 if (!module) {
6842 LOGMEM;
6843 goto error;
6844 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006846 module->ctx = ctx;
6847 module->name = lydict_insert(ctx, value, strlen(value));
6848 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02006849 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02006850
Michal Vasko9f258e42016-02-11 11:36:27 +01006851 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01006852 if (read_sub_module(module, NULL, yin, unres)) {
6853 goto error;
6854 }
6855
6856 /* resolve rest of unres items */
6857 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006858 goto error;
6859 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006860
Radek Krejci95f22ae2017-01-20 14:25:53 +01006861 lyp_sort_revisions(module);
6862
Radek Krejciff4874d2016-03-07 12:30:50 +01006863 if (revision) {
6864 /* check revision of the parsed model */
6865 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01006866 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
6867 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01006868 goto error;
6869 }
6870 }
6871
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006872 /* check correctness of includes */
6873 if (lyp_check_include_missing(module)) {
6874 goto error;
6875 }
6876
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006877 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006878 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006879 }
Radek Krejci63a91a92015-07-29 13:31:04 +02006880
Radek Krejci27fe55e2016-09-13 17:13:35 +02006881 if (module->deviation_size && !module->implemented) {
6882 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
6883 /* deviations always causes target to be made implemented,
6884 * but augents and leafrefs not, so we have to apply them now */
6885 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02006886 goto error;
6887 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006888 }
6889
Michal Vasko345da0a2015-12-02 10:35:55 +01006890 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01006891 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01006892 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006893 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006894
6895error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006896 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01006897 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01006898 unres_schema_free(module, &unres);
6899
6900 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006901 if (ly_vecode != LYVE_SUBMODULE) {
6902 LOGERR(ly_errno, "Module parsing failed.");
6903 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01006904 return NULL;
6905 }
6906
6907 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006908
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006909 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01006910 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006911 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006912}