blob: d9d2c34440445a3812f87ff2be4b9df6e74d1282 [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 *
Michal Vasko53b7da02018-02-13 15:28:42 +01006 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
Radek Krejcida04f4a2015-05-21 12:54:09 +02007 *
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
Michal Vasko53b7da02018-02-13 15:28:42 +010035#define GETVAL(ctx, value, node, arg) \
Radek Krejciadb57612016-02-16 13:34:34 +010036 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Michal Vasko53b7da02018-02-13 15:28:42 +010038 LOGVAL(ctx, 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 Vasko53b7da02018-02-13 15:28:42 +010042#define YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, counter, storage, name, parent, code) \
Radek Krejcidce5f972017-09-12 15:47:49 +020043 if ((counter) == LY_ARRAY_MAX(storage)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +010044 LOGERR(ctx, LY_EINT, "Reached limit (%"PRIu64") for storing %s in %s statement.", \
Radek Krejcidce5f972017-09-12 15:47:49 +020045 LY_ARRAY_MAX(storage), name, parent); \
46 code; \
47 }
48
Michal Vasko53b7da02018-02-13 15:28:42 +010049#define YIN_CHECK_ARRAY_OVERFLOW_RETURN(ctx, counter, storage, name, parent, retval) \
50 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, counter, storage, name, parent, return retval)
Radek Krejcidce5f972017-09-12 15:47:49 +020051
Michal Vasko53b7da02018-02-13 15:28:42 +010052#define YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, counter, storage, name, parent, target) \
53 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, counter, storage, name, parent, goto target)
Radek Krejcidce5f972017-09-12 15:47:49 +020054
Michal Vaskoe022a562016-09-27 14:24:15 +020055#define OPT_IDENT 0x01
56#define OPT_CFG_PARSE 0x02
57#define OPT_CFG_INHERIT 0x04
58#define OPT_CFG_IGNORE 0x08
59#define OPT_MODULE 0x10
Radek Krejci07d0fb92017-01-13 14:11:05 +010060static int read_yin_common(struct lys_module *, struct lys_node *, void *, LYEXT_PAR, struct lyxml_elem *, int,
61 struct unres_schema *);
Radek Krejcib388c152015-06-04 17:03:03 +020062
Radek Krejcib8048692015-08-05 13:36:34 +020063static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010064 int options, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020065static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010066 int options, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020067static 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 +020068 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020069static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010070 int options, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020071static 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 +020072 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020073static 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 +020074 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020075static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010076 int options, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020077static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010078 int options, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020079static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010080 int options, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020081static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010082 int options, struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020083static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010084 int options, struct unres_schema *unres);
Radek Krejci5323b492017-01-16 15:40:11 +010085static 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 +020086
Radek Krejci07d0fb92017-01-13 14:11:05 +010087/*
88 * yin - the provided XML subtree is unlinked
Radek Krejci2b999ac2017-01-18 16:22:12 +010089 * 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 +010090 */
91int
92lyp_yin_fill_ext(void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
Radek Krejci2b999ac2017-01-18 16:22:12 +010093 struct lys_module *module, struct lyxml_elem *yin, struct lys_ext_instance ***ext,
94 uint8_t ext_index, struct unres_schema *unres)
Radek Krejci07d0fb92017-01-13 14:11:05 +010095{
96 struct unres_ext *info;
97
98 info = malloc(sizeof *info);
Michal Vasko53b7da02018-02-13 15:28:42 +010099 LY_CHECK_ERR_RETURN(!info, LOGMEM(module->ctx), EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100100 lyxml_unlink(module->ctx, yin);
101 info->data.yin = yin;
102 info->datatype = LYS_IN_YIN;
103 info->parent = parent;
Radek Krejcia7db9702017-01-20 12:55:14 +0100104 info->mod = module;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100105 info->parent_type = parent_type;
106 info->substmt = substmt;
107 info->substmt_index = substmt_index;
Radek Krejci2b999ac2017-01-18 16:22:12 +0100108 info->ext_index = ext_index;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100109
110 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
111 return EXIT_FAILURE;
112 }
113
114 return EXIT_SUCCESS;
115}
116
Michal Vasko0d343d12015-08-24 14:57:36 +0200117/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200118static const char *
119read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200120{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200121 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200123 /* there should be <text> child */
124 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100125 LOGERR(ctx, LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
126 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +0100127 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200128 } else if (node->child->content) {
129 len = strlen(node->child->content);
130 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +0100131 } else {
132 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200133 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200134}
135
Radek Krejci8d6b7422017-02-03 14:42:13 +0100136int
137lyp_yin_parse_subnode_ext(struct lys_module *mod, void *elem, LYEXT_PAR elem_type,
Radek Krejciac00b2a2017-01-17 14:05:00 +0100138 struct lyxml_elem *yin, LYEXT_SUBSTMT type, uint8_t i, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +0100139{
Radek Krejci07d0fb92017-01-13 14:11:05 +0100140 void *reallocated;
141 struct lyxml_elem *next, *child;
142 int r;
143 struct lys_ext_instance ***ext;
144 uint8_t *ext_size;
Radek Krejcidce5f972017-09-12 15:47:49 +0200145 const char *statement;
Radek Krejcie534c132016-11-23 13:32:31 +0100146
Radek Krejci07d0fb92017-01-13 14:11:05 +0100147 switch (elem_type) {
148 case LYEXT_PAR_MODULE:
149 ext_size = &((struct lys_module *)elem)->ext_size;
150 ext = &((struct lys_module *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200151 statement = ((struct lys_module *)elem)->type ? "submodule" : "module";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100152 break;
Radek Krejci95f22ae2017-01-20 14:25:53 +0100153 case LYEXT_PAR_IMPORT:
154 ext_size = &((struct lys_import *)elem)->ext_size;
155 ext = &((struct lys_import *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200156 statement = "import";
Radek Krejci95f22ae2017-01-20 14:25:53 +0100157 break;
158 case LYEXT_PAR_INCLUDE:
159 ext_size = &((struct lys_include *)elem)->ext_size;
160 ext = &((struct lys_include *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200161 statement = "include";
Radek Krejci95f22ae2017-01-20 14:25:53 +0100162 break;
163 case LYEXT_PAR_REVISION:
164 ext_size = &((struct lys_revision *)elem)->ext_size;
165 ext = &((struct lys_revision *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200166 statement = "revision";
Radek Krejci95f22ae2017-01-20 14:25:53 +0100167 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100168 case LYEXT_PAR_NODE:
169 ext_size = &((struct lys_node *)elem)->ext_size;
170 ext = &((struct lys_node *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200171 statement = strnodetype(((struct lys_node *)elem)->nodetype);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100172 break;
173 case LYEXT_PAR_IDENT:
174 ext_size = &((struct lys_ident *)elem)->ext_size;
175 ext = &((struct lys_ident *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200176 statement = "identity";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100177 break;
Radek Krejci47f7ea52017-01-23 13:14:09 +0100178 case LYEXT_PAR_TYPE:
179 ext_size = &((struct lys_type *)elem)->ext_size;
180 ext = &((struct lys_type *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200181 statement = "type";
Radek Krejci47f7ea52017-01-23 13:14:09 +0100182 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100183 case LYEXT_PAR_TYPE_BIT:
184 ext_size = &((struct lys_type_bit *)elem)->ext_size;
185 ext = &((struct lys_type_bit *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200186 statement = "bit";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100187 break;
188 case LYEXT_PAR_TYPE_ENUM:
189 ext_size = &((struct lys_type_enum *)elem)->ext_size;
190 ext = &((struct lys_type_enum *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200191 statement = "enum";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100192 break;
193 case LYEXT_PAR_TPDF:
194 ext_size = &((struct lys_tpdf *)elem)->ext_size;
195 ext = &((struct lys_tpdf *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200196 statement = " typedef";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100197 break;
198 case LYEXT_PAR_EXT:
199 ext_size = &((struct lys_ext *)elem)->ext_size;
200 ext = &((struct lys_ext *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200201 statement = "extension";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100202 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +0100203 case LYEXT_PAR_EXTINST:
204 ext_size = &((struct lys_ext_instance *)elem)->ext_size;
205 ext = &((struct lys_ext_instance *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200206 statement = "extension instance";
Radek Krejci8d6b7422017-02-03 14:42:13 +0100207 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100208 case LYEXT_PAR_FEATURE:
209 ext_size = &((struct lys_feature *)elem)->ext_size;
210 ext = &((struct lys_feature *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200211 statement = "feature";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100212 break;
213 case LYEXT_PAR_REFINE:
214 ext_size = &((struct lys_refine *)elem)->ext_size;
215 ext = &((struct lys_refine *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200216 statement = "refine";
Radek Krejci07d0fb92017-01-13 14:11:05 +0100217 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +0100218 case LYEXT_PAR_RESTR:
Radek Krejcifccd1442017-01-16 10:26:57 +0100219 ext_size = &((struct lys_restr *)elem)->ext_size;
220 ext = &((struct lys_restr *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200221 statement = "YANG restriction";
Radek Krejcifccd1442017-01-16 10:26:57 +0100222 break;
Radek Krejci5323b492017-01-16 15:40:11 +0100223 case LYEXT_PAR_WHEN:
224 ext_size = &((struct lys_when *)elem)->ext_size;
225 ext = &((struct lys_when *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200226 statement = "when";
Radek Krejci5323b492017-01-16 15:40:11 +0100227 break;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +0100228 case LYEXT_PAR_DEVIATE:
229 ext_size = &((struct lys_deviate *)elem)->ext_size;
230 ext = &((struct lys_deviate *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200231 statement = "deviate";
Radek Krejci3c4b0ea2017-01-24 16:00:47 +0100232 break;
233 case LYEXT_PAR_DEVIATION:
234 ext_size = &((struct lys_deviation *)elem)->ext_size;
235 ext = &((struct lys_deviation *)elem)->ext;
Radek Krejcidce5f972017-09-12 15:47:49 +0200236 statement = "deviation";
Radek Krejci3c4b0ea2017-01-24 16:00:47 +0100237 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100238 default:
Michal Vasko53b7da02018-02-13 15:28:42 +0100239 LOGERR(mod->ctx, LY_EINT, "parent type %d", elem_type);
Radek Krejcie534c132016-11-23 13:32:31 +0100240 return EXIT_FAILURE;
241 }
242
Radek Krejcifccd1442017-01-16 10:26:57 +0100243 if (type == LYEXT_SUBSTMT_SELF) {
244 /* parse for the statement self, not for the substatement */
245 child = yin;
246 next = NULL;
247 goto parseext;
248 }
249
Radek Krejci07d0fb92017-01-13 14:11:05 +0100250 LY_TREE_FOR_SAFE(yin->child, next, child) {
251 if (!strcmp(child->ns->value, LY_NSYIN)) {
252 /* skip the regular YIN nodes */
253 continue;
254 }
255
256 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100257parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100258
Michal Vasko53b7da02018-02-13 15:28:42 +0100259 YIN_CHECK_ARRAY_OVERFLOW_RETURN(mod->ctx, *ext_size, *ext_size, "extension", statement, EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100260 /* first, allocate a space for the extension instance in the parent elem */
261 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100262 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100263 (*ext) = reallocated;
264
265 /* init memory */
266 (*ext)[(*ext_size)] = NULL;
267
268 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100269 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100270 (*ext_size)++;
271 if (r) {
272 return EXIT_FAILURE;
273 }
274
Radek Krejcifccd1442017-01-16 10:26:57 +0100275 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100276 }
277
Radek Krejcie534c132016-11-23 13:32:31 +0100278 return EXIT_SUCCESS;
279}
280
Michal Vasko0d343d12015-08-24 14:57:36 +0200281/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200282static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200283fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
284 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100285{
Radek Krejci5323b492017-01-16 15:40:11 +0100286 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100287 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100288 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100289 struct ly_ctx *ctx = parent->module->ctx;
Michal Vasko1d337e12016-02-15 12:32:04 +0100290
Michal Vasko53b7da02018-02-13 15:28:42 +0100291 GETVAL(ctx, value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200292
293 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100294 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200295error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100296 return EXIT_FAILURE;
297 }
298
Michal Vasko56d082c2016-10-25 14:00:42 +0200299 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100300 return EXIT_FAILURE;
301 }
302
Radek Krejci9de2c042016-10-19 16:53:06 +0200303 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko53b7da02018-02-13 15:28:42 +0100304 lydict_remove(ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200305 if (r) {
306 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100307 }
308
Radek Krejci5323b492017-01-16 15:40:11 +0100309 LY_TREE_FOR_SAFE(yin->child, next, node) {
310 if (!node->ns) {
311 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100312 lyxml_free(ctx, node);
Radek Krejci5323b492017-01-16 15:40:11 +0100313 } else if (strcmp(node->ns->value, LY_NSYIN)) {
314 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100315 YIN_CHECK_ARRAY_OVERFLOW_RETURN(ctx, c_ext, iffeat->ext_size, "extensions", "if-feature", EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100316 c_ext++;
317 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100318 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
Radek Krejci5323b492017-01-16 15:40:11 +0100319 return EXIT_FAILURE;
320 }
321 }
322 if (c_ext) {
323 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100324 LY_CHECK_ERR_RETURN(!iffeat->ext, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100325 LY_TREE_FOR_SAFE(yin->child, next, node) {
326 /* extensions */
327 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100328 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100329 iffeat->ext_size++;
330 if (r) {
331 return EXIT_FAILURE;
332 }
333 }
334 }
335
Radek Krejci9ff0a922016-07-14 13:08:05 +0200336 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100337}
338
339/* logs directly */
340static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200341fill_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 +0200342{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200343 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100344 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200345 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200346 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100347 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100348 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200349
Michal Vasko53b7da02018-02-13 15:28:42 +0100350 GETVAL(ctx, value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100351 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200352
Radek Krejci07d0fb92017-01-13 14:11:05 +0100353 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100354 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 }
Radek Krejci04581c62015-05-22 21:24:00 +0200356
Pavol Vicand6cda452016-07-13 15:08:29 +0200357 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100358 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200359 }
360
Radek Krejcie534c132016-11-23 13:32:31 +0100361 LY_TREE_FOR(yin->child, node) {
362 if (strcmp(node->ns->value, LY_NSYIN)) {
363 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100364 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ident->ext_size, "extensions", "identity", error);
Radek Krejcie534c132016-11-23 13:32:31 +0100365 c_ext++;
366 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200367 if (c_base && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100368 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100369 goto error;
370 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100371 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_base, ident->base_size, "bases", "identity", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +0100372 if (lyp_yin_parse_subnode_ext(module, ident, LYEXT_PAR_IDENT, node, LYEXT_SUBSTMT_BASE, c_base, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100373 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200374 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200375 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100376
Radek Krejci018f1f52016-08-03 16:01:20 +0200377 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100378 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, ident->iffeature_size, "if-features", "identity", error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200379 c_ftrs++;
380
381 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100382 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100383 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200384 }
385 }
386
387 if (c_base) {
388 ident->base_size = 0;
389 ident->base = calloc(c_base, sizeof *ident->base);
Michal Vasko53b7da02018-02-13 15:28:42 +0100390 LY_CHECK_ERR_GOTO(!ident->base, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200391 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200392 if (c_ftrs) {
393 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +0100394 LY_CHECK_ERR_GOTO(!ident->iffeature, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200395 }
Radek Krejcie534c132016-11-23 13:32:31 +0100396 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100397 /* some extensions may be already present from the substatements */
398 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100399 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci18a44882017-01-23 13:47:29 +0100400 ident->ext = reallocated;
401
402 /* init memory */
403 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100404 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200405
Radek Krejcie534c132016-11-23 13:32:31 +0100406 LY_TREE_FOR_SAFE(yin->child, next, node) {
407 if (strcmp(node->ns->value, LY_NSYIN)) {
408 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100409 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 +0100410 ident->ext_size++;
411 if (rc) {
412 goto error;
413 }
414 } else if (!strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100415 GETVAL(ctx, value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100416 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100417 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100418 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200419 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100420
Radek Krejci48464ed2016-03-17 15:44:09 +0100421 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100422 lydict_remove(ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100423 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100424 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100425 lydict_remove(ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200426 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200427 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200428 ident->iffeature_size++;
429 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100430 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200431 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200432 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200433 }
Radek Krejci04581c62015-05-22 21:24:00 +0200434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200435 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200436
437error:
438 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200439}
440
Michal Vasko0d343d12015-08-24 14:57:36 +0200441/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200442static int
Radek Krejciaa9c5202017-02-15 16:10:14 +0100443read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
Radek Krejcifccd1442017-01-16 10:26:57 +0100444 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200445{
Radek Krejcifccd1442017-01-16 10:26:57 +0100446 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200447 const char *value;
Michal Vasko53b7da02018-02-13 15:28:42 +0100448 struct ly_ctx *ctx = module->ctx;
Radek Krejci41726f92015-06-19 13:11:05 +0200449
Radek Krejcifccd1442017-01-16 10:26:57 +0100450 LY_TREE_FOR_SAFE(yin->child, next, child) {
451 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200452 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200453 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100454 } else if (strcmp(child->ns->value, LY_NSYIN)) {
455 /* extension */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100456 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100457 return EXIT_FAILURE;
458 }
459 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200460 if (restr->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100461 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200462 return EXIT_FAILURE;
463 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100464 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100465 return EXIT_FAILURE;
466 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100467 restr->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200468 if (!restr->dsc) {
469 return EXIT_FAILURE;
470 }
471 } else if (!strcmp(child->name, "reference")) {
472 if (restr->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100473 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200474 return EXIT_FAILURE;
475 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100476 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100477 return EXIT_FAILURE;
478 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100479 restr->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200480 if (!restr->ref) {
481 return EXIT_FAILURE;
482 }
483 } else if (!strcmp(child->name, "error-app-tag")) {
484 if (restr->eapptag) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100485 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200486 return EXIT_FAILURE;
487 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100488 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100489 return EXIT_FAILURE;
490 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100491 GETVAL(ctx, value, child, "value");
492 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200493 } else if (!strcmp(child->name, "error-message")) {
494 if (restr->emsg) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100495 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200496 return EXIT_FAILURE;
497 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100498 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100499 return EXIT_FAILURE;
500 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100501 restr->emsg = read_yin_subnode(ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200502 if (!restr->emsg) {
503 return EXIT_FAILURE;
504 }
505 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100506 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200507 return EXIT_FAILURE;
508 }
Radek Krejci41726f92015-06-19 13:11:05 +0200509 }
510
511 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200512
513error:
514 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200515}
516
Michal Vasko88c29542015-11-27 14:57:53 +0100517/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
518int
Radek Krejcib8048692015-08-05 13:36:34 +0200519fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci8d6b7422017-02-03 14:42:13 +0100520 int parenttype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200521{
Michal Vasko568b1952018-01-30 15:53:30 +0100522 const char *value, *name, *module_name = NULL;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200523 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100524 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100525 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200526 struct lys_type_bit bit, *bits_sc = NULL;
527 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200528 struct lys_type *dertype;
Michal Vasko53b7da02018-02-13 15:28:42 +0100529 struct ly_ctx *ctx = module->ctx;
Radek Krejcidce5f972017-09-12 15:47:49 +0200530 int rc, val_set, c_ftrs, c_ext = 0;
531 unsigned int i, j;
Radek Krejcidc008d72016-02-17 13:12:14 +0100532 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200533 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200534 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200535 size_t len;
Radek Krejcib53154b2017-07-19 09:14:13 +0200536 int in_grp = 0;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200537 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200538
Radek Krejcie534c132016-11-23 13:32:31 +0100539 /* init */
540 memset(&exts, 0, sizeof exts);
541
Michal Vasko53b7da02018-02-13 15:28:42 +0100542 GETVAL(ctx, value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100543 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200544 if (!value) {
545 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200546 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200547
548 i = parse_identifier(value);
549 if (i < 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100550 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
551 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200552 goto error;
553 }
554 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100555 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200556 if (value[i]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100557 module_name = lydict_insert(ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100558 name += i;
559 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100560 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
561 lydict_remove(ctx, module_name);
562 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200563 goto error;
564 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200565 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100566 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200567 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200568
Michal Vasko568b1952018-01-30 15:53:30 +0100569 rc = resolve_superior_type(name, module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200570 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100571 LOGVAL(ctx, LYE_INMOD, LY_VLOG_NONE, NULL, module_name);
572 lydict_remove(ctx, module_name);
573 lydict_remove(ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200574 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100575
576 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200577 } else if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100578 LOGVAL(ctx, LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
579 lydict_remove(ctx, module_name);
580 lydict_remove(ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100581 ret = EXIT_FAILURE;
582 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100584 lydict_remove(ctx, module_name);
585 lydict_remove(ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200586
Radek Krejci9b6aad22016-09-20 15:55:51 +0200587 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200588 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200589 * 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 +0200590 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
591 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200592 assert(((struct lys_node_grp *)siter)->unres_count);
593 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200594 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100595 LOGINT(ctx);
Radek Krejcic13db382016-08-16 10:52:42 +0200596 goto error;
597 }
598 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200600
Radek Krejcicf509982015-12-15 09:22:44 +0100601 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100602 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Michal Vasko53b7da02018-02-13 15:28:42 +0100603 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100604 return -1;
605 }
606
Radek Krejcie534c132016-11-23 13:32:31 +0100607 /* parse extension instances */
608 LY_TREE_FOR_SAFE(yin->child, next, node) {
609 if (!node->ns) {
610 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100611 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100612 continue;
613 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
614 /* YANG (YIN) statements - process later */
615 continue;
616 }
617
Michal Vasko53b7da02018-02-13 15:28:42 +0100618 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, type->ext_size, "extensions", "type", error);
Radek Krejcidce5f972017-09-12 15:47:49 +0200619
Michal Vasko53b7da02018-02-13 15:28:42 +0100620 lyxml_unlink_elem(ctx, node, 2);
621 lyxml_add_child(ctx, &exts, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100622 c_ext++;
623 }
624 if (c_ext) {
625 type->ext = calloc(c_ext, sizeof *type->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100626 LY_CHECK_ERR_GOTO(!type->ext, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200627
Radek Krejcie534c132016-11-23 13:32:31 +0100628 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100629 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 +0100630 type->ext_size++;
631 if (rc) {
632 goto error;
633 }
634 }
635 }
636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200637 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200639 /* RFC 6020 9.7.4 - bit */
640
641 /* get bit specifications, at least one must be present */
642 LY_TREE_FOR_SAFE(yin->child, next, node) {
643 if (!strcmp(node->name, "bit")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100644 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.bits.count, type->info.bits.count, "bits", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200645 type->info.bits.count = 0; goto error);
Radek Krejci994b6f62015-06-18 16:47:27 +0200646 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200647 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100648 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200649 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200650 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200651 }
652 }
Radek Krejcie663e012016-08-01 17:12:34 +0200653 dertype = &type->der->type;
654 if (!dertype->der) {
655 if (!type->info.bits.count) {
656 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100657 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200658 goto error;
659 }
660 } else {
661 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
662 if (module->version < 2 && type->info.bits.count) {
663 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
664 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100665 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200666 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200667 goto error;
668 }
Radek Krejciac781922015-07-09 15:35:14 +0200669 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200670
671 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +0100672 LY_CHECK_ERR_GOTO(!type->info.bits.bit, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200673
Radek Krejci73adb602015-07-02 18:07:40 +0200674 p = 0;
675 i = -1;
676 LY_TREE_FOR(yin->child, next) {
677 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200678 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200679
Michal Vasko53b7da02018-02-13 15:28:42 +0100680 GETVAL(ctx, value, next, "name");
681 if (lyp_check_identifier(ctx, value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100682 goto error;
683 }
684
Michal Vasko53b7da02018-02-13 15:28:42 +0100685 type->info.bits.bit[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100686 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 +0200687 type->info.bits.count = i + 1;
688 goto error;
689 }
690
Radek Krejcie663e012016-08-01 17:12:34 +0200691 if (!dertype->der) { /* directly derived type from bits built-in type */
692 /* check the name uniqueness */
693 for (j = 0; j < i; j++) {
694 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100695 LOGVAL(ctx, LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejcie663e012016-08-01 17:12:34 +0200696 type->info.bits.count = i + 1;
697 goto error;
698 }
699 }
700 } else {
701 /* restricted bits type - the name MUST be used in the base type */
702 bits_sc = dertype->info.bits.bit;
703 for (j = 0; j < dertype->info.bits.count; j++) {
704 if (ly_strequal(bits_sc[j].name, value, 1)) {
705 break;
706 }
707 }
708 if (j == dertype->info.bits.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100709 LOGVAL(ctx, LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200710 type->info.bits.count = i + 1;
711 goto error;
712 }
713 }
714
Radek Krejcie663e012016-08-01 17:12:34 +0200715
Radek Krejci0d70c372015-07-02 16:23:10 +0200716 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100717 LY_TREE_FOR_SAFE(next->child, next2, node) {
718 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200719 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200720 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100721 } else if (strcmp(node->ns->value, LY_NSYIN)) {
722 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100723 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Michal Vasko53b7da02018-02-13 15:28:42 +0100724 LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci9b15fea2017-01-23 11:31:43 +0100725 goto error;
726 }
727 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200728 if (p_ != -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100729 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +0200730 type->info.bits.count = i + 1;
731 goto error;
732 }
733
Michal Vasko53b7da02018-02-13 15:28:42 +0100734 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200735 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200736
737 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200738 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100739 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200740 type->info.bits.count = i + 1;
741 goto error;
742 }
743 type->info.bits.bit[i].pos = (uint32_t)p_;
744
Radek Krejcie663e012016-08-01 17:12:34 +0200745 if (!dertype->der) { /* directly derived type from bits built-in type */
746 /* keep the highest enum value for automatic increment */
747 if (type->info.bits.bit[i].pos >= p) {
748 p = type->info.bits.bit[i].pos;
749 p++;
750 } else {
751 /* check that the value is unique */
752 for (j = 0; j < i; j++) {
753 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100754 LOGVAL(ctx, LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +0200755 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
756 type->info.bits.bit[j].name);
757 type->info.bits.count = i + 1;
758 goto error;
759 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200760 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200761 }
762 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200763
Radek Krejci8d6b7422017-02-03 14:42:13 +0100764 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100765 LYEXT_SUBSTMT_POSITION, 0, unres)) {
766 goto error;
767 }
PavolVican92f23622017-12-12 13:35:56 +0100768
PavolVican0144fae2018-02-05 15:54:17 +0100769 for (j = 0; j < type->info.bits.bit[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100770 /* set flag, which represent LYEXT_OPT_VALID */
771 if (type->info.bits.bit[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100772 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100773 break;
774 }
775 }
776
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200777 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100778 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, type->info.bits.bit[i].iffeature_size, "if-features", "bit", error);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200779 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200780 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100781 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200782 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200783 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200784 }
Radek Krejcie663e012016-08-01 17:12:34 +0200785
786 if (!dertype->der) { /* directly derived type from bits built-in type */
787 if (p_ == -1) {
788 /* assign value automatically */
789 if (p > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100790 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejcie663e012016-08-01 17:12:34 +0200791 type->info.bits.count = i + 1;
792 goto error;
793 }
794 type->info.bits.bit[i].pos = (uint32_t)p;
795 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
796 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200797 }
Radek Krejcie663e012016-08-01 17:12:34 +0200798 } else { /* restricted bits type */
799 if (p_ == -1) {
800 /* automatically assign position from base type */
801 type->info.bits.bit[i].pos = bits_sc[j].pos;
802 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
803 } else {
804 /* check that the assigned position corresponds to the original
805 * position of the bit in the base type */
806 if (p_ != bits_sc[j].pos) {
807 /* p_ - assigned position in restricted bits
808 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100809 LOGVAL(ctx, LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200810 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200811 type->info.bits.count = i + 1;
812 goto error;
813 }
814 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200815 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200816
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200817 /* if-features */
818 if (c_ftrs) {
819 bits_sc = &type->info.bits.bit[i];
820 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
821 if (!bits_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100822 LOGMEM(ctx);
Radek Krejci994b6f62015-06-18 16:47:27 +0200823 type->info.bits.count = i + 1;
824 goto error;
825 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200826
827 LY_TREE_FOR(next->child, node) {
828 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200829 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200830 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
831 bits_sc->iffeature_size++;
832 if (rc) {
833 type->info.bits.count = i + 1;
834 goto error;
835 }
836 }
837 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200838 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200839
840 /* keep them ordered by position */
841 j = i;
842 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
843 /* switch them */
844 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
845 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
846 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
847 j--;
848 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200849 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200853 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200854 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200855
Radek Krejcif9401c32015-06-26 16:47:36 +0200856 if (!strcmp(node->name, "range")) {
857 if (type->info.dec64.range) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100858 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200859 goto error;
860 }
861
Michal Vasko53b7da02018-02-13 15:28:42 +0100862 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200863 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko53b7da02018-02-13 15:28:42 +0100864 LY_CHECK_ERR_GOTO(!type->info.dec64.range, LOGMEM(ctx), error);
865 type->info.dec64.range->expr = lydict_insert(ctx, value, 0);
Radek Krejcif9401c32015-06-26 16:47:36 +0200866
867 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100868 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200869 goto error;
870 }
PavolVican0144fae2018-02-05 15:54:17 +0100871 for (j = 0; j < type->info.dec64.range->ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100872 /* set flag, which represent LYEXT_OPT_VALID */
873 if (type->info.dec64.range->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100874 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100875 break;
876 }
877 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200878 } else if (!strcmp(node->name, "fraction-digits")) {
879 if (type->info.dec64.dig) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100880 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200881 goto error;
882 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100883 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200884 v = strtol(value, NULL, 10);
885
886 /* range check */
887 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100888 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200889 goto error;
890 }
891 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200892 type->info.dec64.div = 10;
893 for (i = 1; i < v; i++) {
894 type->info.dec64.div *= 10;
895 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100896
897 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100898 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100899 goto error;
900 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200901 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100902 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200903 goto error;
904 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200905 }
906
907 /* mandatory sub-statement(s) check */
908 if (!type->info.dec64.dig && !type->der->type.der) {
909 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vasko53b7da02018-02-13 15:28:42 +0100910 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200911 goto error;
912 }
Radek Krejci7511f402015-07-10 09:56:30 +0200913 if (type->info.dec64.dig && type->der->type.der) {
914 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vasko53b7da02018-02-13 15:28:42 +0100915 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200916 goto error;
917 }
Radek Krejci4800f652016-09-08 14:02:52 +0200918
919 /* copy fraction-digits specification from parent type for easier internal use */
920 if (type->der->type.der) {
921 type->info.dec64.dig = type->der->type.info.dec64.dig;
922 type->info.dec64.div = type->der->type.info.dec64.div;
923 }
924
Michal Vasko53b7da02018-02-13 15:28:42 +0100925 if (type->info.dec64.range && lyp_check_length_range(ctx, type->info.dec64.range->expr, type)) {
926 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200927 goto error;
928 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200929 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200931 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200932 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200933
Radek Krejci994b6f62015-06-18 16:47:27 +0200934 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 if (!strcmp(node->name, "enum")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100938 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.enums.count, type->info.enums.count, "enums", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200939 type->info.enums.count = 0; goto error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200941 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100942 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200943 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200944 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200945 }
946 }
Radek Krejcie663e012016-08-01 17:12:34 +0200947 dertype = &type->der->type;
948 if (!dertype->der) {
949 if (!type->info.enums.count) {
950 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100951 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200952 goto error;
953 }
954 } else {
955 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
956 if (module->version < 2 && type->info.enums.count) {
957 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
958 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100959 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200960 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200961 goto error;
962 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200963 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200964
Radek Krejci1574a8d2015-08-03 14:16:52 +0200965 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +0100966 LY_CHECK_ERR_GOTO(!type->info.enums.enm, LOGMEM(ctx), error);
Radek Krejcifc8d8322016-06-24 11:23:23 +0200967
Radek Krejcie663e012016-08-01 17:12:34 +0200968 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200969 i = -1;
970 LY_TREE_FOR(yin->child, next) {
971 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200972 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200973
Michal Vasko53b7da02018-02-13 15:28:42 +0100974 GETVAL(ctx, value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100975 if (!value[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100976 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
977 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100978 goto error;
979 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100980 type->info.enums.enm[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100981 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 +0200982 type->info.enums.count = i + 1;
983 goto error;
984 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200986 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200987 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200988 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100989 LOGVAL(ctx, LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 type->info.enums.count = i + 1;
991 goto error;
992 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200993
Radek Krejcie663e012016-08-01 17:12:34 +0200994 if (!dertype->der) { /* directly derived type from enumeration built-in type */
995 /* check the name uniqueness */
996 for (j = 0; j < i; j++) {
997 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100998 LOGVAL(ctx, LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
Radek Krejcie663e012016-08-01 17:12:34 +0200999 type->info.enums.count = i + 1;
1000 goto error;
1001 }
1002 }
1003 } else {
1004 /* restricted enumeration type - the name MUST be used in the base type */
1005 enms_sc = dertype->info.enums.enm;
1006 for (j = 0; j < dertype->info.enums.count; j++) {
1007 if (ly_strequal(enms_sc[j].name, value, 1)) {
1008 break;
1009 }
1010 }
1011 if (j == dertype->info.enums.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001012 LOGVAL(ctx, LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001013 type->info.enums.count = i + 1;
1014 goto error;
1015 }
1016 }
Radek Krejci04581c62015-05-22 21:24:00 +02001017
Radek Krejcie663e012016-08-01 17:12:34 +02001018 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001019 LY_TREE_FOR_SAFE(next->child, next2, node) {
1020 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001021 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001022 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001023 } else if (strcmp(node->ns->value, LY_NSYIN)) {
1024 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001025 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001026 LYEXT_SUBSTMT_SELF, 0, unres)) {
1027 goto error;
1028 }
1029 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +02001030 if (val_set) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001031 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +02001032 type->info.enums.count = i + 1;
1033 goto error;
1034 }
1035
Michal Vasko53b7da02018-02-13 15:28:42 +01001036 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +02001037 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +02001038
1039 /* range check */
1040 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001041 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +02001042 type->info.enums.count = i + 1;
1043 goto error;
1044 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001045 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +02001046
Radek Krejcie663e012016-08-01 17:12:34 +02001047 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001048 if (!i) {
1049 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001050 v = type->info.enums.enm[i].value;
1051 v++;
1052 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001053 /* keep the highest enum value for automatic increment */
1054 if (type->info.enums.enm[i].value >= v) {
1055 v = type->info.enums.enm[i].value;
1056 v++;
1057 } else {
1058 /* check that the value is unique */
1059 for (j = 0; j < i; j++) {
1060 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001061 LOGVAL(ctx, LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican5de389c2016-08-30 08:55:15 +02001062 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1063 type->info.enums.enm[j].name);
1064 type->info.enums.count = i + 1;
1065 goto error;
1066 }
Radek Krejcie663e012016-08-01 17:12:34 +02001067 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001068 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069 }
1070 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001071 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001072
Radek Krejci8d6b7422017-02-03 14:42:13 +01001073 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001074 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1075 goto error;
1076 }
PavolVican92f23622017-12-12 13:35:56 +01001077
PavolVican0144fae2018-02-05 15:54:17 +01001078 for (j = 0; j < type->info.enums.enm[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +01001079 /* set flag, which represent LYEXT_OPT_VALID */
1080 if (type->info.enums.enm[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001081 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001082 break;
1083 }
1084 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001085 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001086 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, type->info.enums.enm[i].iffeature_size, "if-features", "enum", error);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001087 c_ftrs++;
1088
Radek Krejci0d70c372015-07-02 16:23:10 +02001089 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001090 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001091 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001092 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001093 }
Radek Krejcie663e012016-08-01 17:12:34 +02001094
1095 if (!dertype->der) { /* directly derived type from enumeration */
1096 if (!val_set) {
1097 /* assign value automatically */
1098 if (v > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001099 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejcie663e012016-08-01 17:12:34 +02001100 type->info.enums.count = i + 1;
1101 goto error;
1102 }
1103 type->info.enums.enm[i].value = v;
1104 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1105 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 }
Radek Krejcie663e012016-08-01 17:12:34 +02001107 } else { /* restricted enum type */
1108 if (!val_set) {
1109 /* automatically assign value from base type */
1110 type->info.enums.enm[i].value = enms_sc[j].value;
1111 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1112 } else {
1113 /* check that the assigned value corresponds to the original
1114 * value of the enum in the base type */
1115 if (v_ != enms_sc[j].value) {
1116 /* v_ - assigned value in restricted enum
1117 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001118 LOGVAL(ctx, LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001119 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001120 type->info.enums.count = i + 1;
1121 goto error;
1122 }
1123 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001125
1126 /* if-features */
1127 if (c_ftrs) {
1128 enms_sc = &type->info.enums.enm[i];
1129 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1130 if (!enms_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001131 LOGMEM(ctx);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132 type->info.enums.count = i + 1;
1133 goto error;
1134 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001135
1136 LY_TREE_FOR(next->child, node) {
1137 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001138 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001139 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1140 enms_sc->iffeature_size++;
1141 if (rc) {
1142 type->info.enums.count = i + 1;
1143 goto error;
1144 }
1145 }
1146 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001147 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001149 }
1150 break;
1151
1152 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001153 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154
Michal Vaskof2d43962016-09-02 11:10:16 +02001155 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001156 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001157
Michal Vaskoe29c6622015-11-27 15:02:31 +01001158 if (strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001159 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001160 goto error;
1161 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001162
Michal Vasko53b7da02018-02-13 15:28:42 +01001163 GETVAL(ctx, value, yin->child, "name");
Michal Vaskof2d43962016-09-02 11:10:16 +02001164 /* store in the JSON format */
1165 value = transform_schema2json(module, value);
1166 if (!value) {
1167 goto error;
1168 }
1169 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Michal Vasko53b7da02018-02-13 15:28:42 +01001170 lydict_remove(ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001171 if (rc == -1) {
1172 goto error;
1173 }
Radek Krejci18a44882017-01-23 13:47:29 +01001174
Radek Krejci8d6b7422017-02-03 14:42:13 +01001175 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001176 goto error;
1177 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001178 }
1179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001180 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001181 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001182 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001183 break;
1184 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001185 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001187 } else {
1188 if (type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001189 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
Pavol Vicanf0046f42016-09-07 15:11:09 +02001190 goto error;
1191 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001192 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 if (yin->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001194 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 goto error;
1196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001197 break;
1198
1199 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001200 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001201 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001202
Radek Krejciaf351422015-06-19 14:49:38 +02001203 if (!strcmp(node->name, "require-instance")) {
1204 if (type->info.inst.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001205 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001206 goto error;
1207 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001208 GETVAL(ctx, value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001209 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001210 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001211 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001212 type->info.inst.req = -1;
1213 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001214 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001215 goto error;
1216 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001217
1218 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001219 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001220 goto error;
1221 }
Radek Krejciaf351422015-06-19 14:49:38 +02001222 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001223 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001224 goto error;
1225 }
Radek Krejciaf351422015-06-19 14:49:38 +02001226 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001228 break;
1229
Radek Krejcif2860132015-06-20 12:37:20 +02001230 case LY_TYPE_BINARY:
1231 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 case LY_TYPE_INT8:
1233 case LY_TYPE_INT16:
1234 case LY_TYPE_INT32:
1235 case LY_TYPE_INT64:
1236 case LY_TYPE_UINT8:
1237 case LY_TYPE_UINT16:
1238 case LY_TYPE_UINT32:
1239 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001240 /* RFC 6020 9.2.4 - range */
1241
1242 /* length and range are actually the same restriction, so process
1243 * them by this common code, we just need to differ the name and
1244 * structure where the information will be stored
1245 */
1246 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001247 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001248 name = "length";
1249 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001250 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001251 name = "range";
1252 }
1253
Radek Krejci73adb602015-07-02 18:07:40 +02001254 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001255
Radek Krejcif2860132015-06-20 12:37:20 +02001256 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001257 if (*restrs) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001258 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001259 goto error;
1260 }
1261
Michal Vasko53b7da02018-02-13 15:28:42 +01001262 GETVAL(ctx, value, node, "value");
1263 if (lyp_check_length_range(ctx, value, type)) {
1264 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001265 goto error;
1266 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001267 *restrs = calloc(1, sizeof **restrs);
Michal Vasko53b7da02018-02-13 15:28:42 +01001268 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM(ctx), error);
1269 (*restrs)->expr = lydict_insert(ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001270
1271 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001272 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001273 goto error;
1274 }
PavolVican92f23622017-12-12 13:35:56 +01001275
1276 for (j = 0; j < (*restrs)->ext_size; ++j) {
1277 /* set flag, which represent LYEXT_OPT_VALID */
1278 if ((*restrs)->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001279 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001280 break;
1281 }
1282 }
Radek Krejcif2860132015-06-20 12:37:20 +02001283 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001284 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001285 goto error;
1286 }
Radek Krejcif2860132015-06-20 12:37:20 +02001287 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001288 break;
1289
1290 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001291 /* flag resolving for later use */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001292 if (!parenttype) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001293 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1294 if (siter) {
1295 /* just a flag - do not resolve */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001296 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001297 }
1298 }
1299
Radek Krejcidc4c1412015-06-19 15:39:54 +02001300 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001301 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001302
Michal Vasko88c29542015-11-27 14:57:53 +01001303 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001304 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001305 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001306 goto error;
1307 }
1308
Michal Vasko53b7da02018-02-13 15:28:42 +01001309 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001310 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001311 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001312 if (!type->info.lref.path) {
1313 goto error;
1314 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001315
1316 /* try to resolve leafref path only when this is instantiated
1317 * leaf, so it is not:
1318 * - typedef's type,
1319 * - in grouping definition,
1320 * - just instantiated in a grouping definition,
1321 * because in those cases the nodes referenced in path might not be present
1322 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001323 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001324 goto error;
1325 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001326
1327 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001328 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001329 goto error;
1330 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001331 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001332 if (type->info.lref.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001333 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001334 goto error;
1335 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001336 GETVAL(ctx, value, node, "value");
Michal Vasko08ae53e2016-09-02 12:40:04 +02001337 if (!strcmp(value, "true")) {
1338 type->info.lref.req = 1;
1339 } else if (!strcmp(value, "false")) {
1340 type->info.lref.req = -1;
1341 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001342 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001343 goto error;
1344 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001345
1346 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001347 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001348 goto error;
1349 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001350 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001351 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001352 goto error;
1353 }
Radek Krejci73adb602015-07-02 18:07:40 +02001354 }
1355
Radek Krejci742be352016-07-17 12:18:54 +02001356 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001357 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001358 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001359 goto error;
1360 } else {
1361 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001362 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001363 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001364 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001365 goto error;
1366 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001367 }
Radek Krejci742be352016-07-17 12:18:54 +02001368 }
1369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001370 break;
1371
1372 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001373 /* RFC 6020 9.4.4 - length */
1374 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001375 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001376 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001377
Radek Krejci3733a802015-06-19 13:43:21 +02001378 if (!strcmp(node->name, "length")) {
1379 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001380 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001381 goto error;
1382 }
1383
Michal Vasko53b7da02018-02-13 15:28:42 +01001384 GETVAL(ctx, value, node, "value");
1385 if (lyp_check_length_range(ctx, value, type)) {
1386 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001387 goto error;
1388 }
1389 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001390 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1391 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001392
Radek Krejci5fbc9162015-06-19 14:11:11 +02001393 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001394 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001395 goto error;
1396 }
PavolVican92f23622017-12-12 13:35:56 +01001397
1398 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1399 /* set flag, which represent LYEXT_OPT_VALID */
1400 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001401 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001402 break;
1403 }
1404 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001405 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001406 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001407 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001408 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001409 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001410 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001411 goto error;
1412 }
1413 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001414 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001415 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001416 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001417 in_grp = 1;
1418 }
Radek Krejci73adb602015-07-02 18:07:40 +02001419 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001420 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001421#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001422 if (!in_grp) {
1423 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001424 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001425 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001426 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001427#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001428 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001429 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001430
Michal Vasko53b7da02018-02-13 15:28:42 +01001431 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vaskofcd974b2017-08-22 10:17:49 +02001432 if (in_grp) {
1433 /* in grouping, just check the pattern syntax */
Michal Vasko53b7da02018-02-13 15:28:42 +01001434 if (lyp_check_pattern(ctx, value, NULL)) {
Michal Vaskofcd974b2017-08-22 10:17:49 +02001435 goto error;
1436 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001437 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001438#ifdef LY_ENABLED_CACHE
1439 else {
1440 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
Michal Vaskoa26db302018-02-14 15:22:10 +01001441 if (lyp_precompile_pattern(ctx, value,
Michal Vaskofcd974b2017-08-22 10:17:49 +02001442 (pcre**)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1443 (pcre_extra**)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1444 goto error;
1445 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001446 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001447#endif
Michal Vasko69068852015-07-13 14:34:31 +02001448 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001449 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001450 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001451
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001452 modifier = 0x06; /* ACK */
1453 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001454 if (module->version >= 2) {
1455 LY_TREE_FOR_SAFE(node->child, next2, child) {
1456 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1457 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001458 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001459 goto error;
1460 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001461
Michal Vasko53b7da02018-02-13 15:28:42 +01001462 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001463 if (!strcmp(name, "invert-match")) {
1464 modifier = 0x15; /* NACK */
1465 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001466 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001467 goto error;
1468 }
1469 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001470 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001471 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1472 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001473 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001474
Michal Vasko53b7da02018-02-13 15:28:42 +01001475 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001476 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001477 }
1478 }
1479
1480 len = strlen(value);
1481 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001482 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001483 buf[0] = modifier;
1484 strcpy(&buf[1], value);
1485
Michal Vasko53b7da02018-02-13 15:28:42 +01001486 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001487
1488 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001489 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001490 goto error;
1491 }
PavolVican92f23622017-12-12 13:35:56 +01001492
1493 for (j = 0; j < restr->ext_size; ++j) {
1494 /* set flag, which represent LYEXT_OPT_VALID */
1495 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001496 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001497 break;
1498 }
1499 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001500 }
1501 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001502 break;
1503
1504 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001505 /* RFC 6020 7.4 - type */
1506 /* count number of types in union */
1507 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001508 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001509
Radek Krejcie4c366b2015-07-02 10:11:31 +02001510 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001511 if (type->der->type.der) {
1512 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001513 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001514 goto error;
1515 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001516 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001517 i++;
1518 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001519 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001520 goto error;
1521 }
1522 }
1523
Radek Krejci038d5d92016-09-12 15:07:15 +02001524 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001525 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001526 goto error;
1527 }
1528
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001529 /* inherit instid presence information */
1530 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1531 type->info.uni.has_ptr_type = 1;
1532 }
1533
Radek Krejcie4c366b2015-07-02 10:11:31 +02001534 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001535 if (i) {
1536 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001537 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001538 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001539
Radek Krejcie4c366b2015-07-02 10:11:31 +02001540 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001541 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001542 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001543 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001544 if (!rc) {
1545 type->info.uni.count++;
1546
Radek Krejci7de36cf2016-09-12 16:18:50 +02001547 if (module->version < 2) {
1548 /* union's type cannot be empty or leafref */
1549 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001550 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001551 rc = -1;
1552 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001553 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001554 rc = -1;
1555 }
Michal Vasko88c29542015-11-27 14:57:53 +01001556 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001557
1558 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001559 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1560 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1561 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001562 type->info.uni.has_ptr_type = 1;
1563 }
Michal Vasko88c29542015-11-27 14:57:53 +01001564 }
1565 if (rc) {
1566 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1567 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001568 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001569 }
1570 free(type->info.uni.types);
1571 type->info.uni.types = NULL;
1572 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001573 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001574 type->der = NULL;
1575 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001576
1577 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001578 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001579 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001580 goto error;
1581 }
Michal Vasko88c29542015-11-27 14:57:53 +01001582 }
1583 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001584
Michal Vasko88c29542015-11-27 14:57:53 +01001585 case LY_TYPE_BOOL:
1586 case LY_TYPE_EMPTY:
1587 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001588 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001589 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001590 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 break;
1593
1594 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001595 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001596 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 }
1598
PavolVican92f23622017-12-12 13:35:56 +01001599 for(j = 0; j < type->ext_size; ++j) {
1600 /* set flag, which represent LYEXT_OPT_VALID */
1601 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001602 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001603 break;
1604 }
1605 }
1606
1607 /* if derived type has extension, which need validate data */
1608 dertype = &type->der->type;
1609 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001610 if (dertype->parent->flags & LYS_VALID_EXT) {
1611 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001612 }
1613 dertype = &dertype->der->type;
1614 }
1615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001617
1618error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001619 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001620 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001621}
1622
Michal Vasko0d343d12015-08-24 14:57:36 +02001623/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001625fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1626 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001627{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001629 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001630 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001631 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001632 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001633
Michal Vasko53b7da02018-02-13 15:28:42 +01001634 GETVAL(ctx, value, yin, "name");
1635 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 goto error;
1637 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001638 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001641 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 goto error;
1643 }
Radek Krejcieac35532015-05-31 19:09:15 +02001644
Michal Vasko88c29542015-11-27 14:57:53 +01001645 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001646 if (strcmp(node->ns->value, LY_NSYIN)) {
1647 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001648 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001649 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001650 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001651 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001652 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001653 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 goto error;
1655 }
Michal Vasko88c29542015-11-27 14:57:53 +01001656 /* HACK for unres */
1657 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001658 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001659 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001660 goto error;
1661 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001662 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001663
Radek Krejci07d0fb92017-01-13 14:11:05 +01001664 /* 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 +01001665 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 } else if (!strcmp(node->name, "default")) {
1667 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001668 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001669 goto error;
1670 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001671 GETVAL(ctx, value, node, "value");
1672 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001673
Radek Krejci8d6b7422017-02-03 14:42:13 +01001674 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001675 goto error;
1676 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 } else if (!strcmp(node->name, "units")) {
1678 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001679 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 goto error;
1681 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001682 GETVAL(ctx, value, node, "name");
1683 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001684
Radek Krejci8d6b7422017-02-03 14:42:13 +01001685 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001686 goto error;
1687 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001689 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 goto error;
1691 }
Radek Krejcie534c132016-11-23 13:32:31 +01001692
Michal Vasko53b7da02018-02-13 15:28:42 +01001693 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001697 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001698 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001699 goto error;
1700 }
Radek Krejcieac35532015-05-31 19:09:15 +02001701
Michal Vasko478c4652016-07-21 12:55:01 +02001702 /* check default value (if not defined, there still could be some restrictions
1703 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001704 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001705 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001706 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001707 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001708
Radek Krejcie534c132016-11-23 13:32:31 +01001709 /* finish extensions parsing */
1710 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001711 /* some extensions may be already present from the substatements */
1712 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001713 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001714 tpdf->ext = reallocated;
1715
1716 /* init memory */
1717 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1718
Radek Krejcie534c132016-11-23 13:32:31 +01001719 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001720 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 +01001721 tpdf->ext_size++;
1722 if (rc) {
1723 goto error;
1724 }
1725 }
1726 }
1727
PavolVican92f23622017-12-12 13:35:56 +01001728 for (i = 0; i < tpdf->ext_size; ++i) {
1729 /* set flag, which represent LYEXT_OPT_VALID */
1730 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001731 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001732 break;
1733 }
1734 }
1735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001737
1738error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001739 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001740}
1741
Radek Krejcia1a6b762016-11-14 09:53:38 +09001742static int
Radek Krejcie534c132016-11-23 13:32:31 +01001743fill_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 +09001744{
Michal Vasko53b7da02018-02-13 15:28:42 +01001745 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001746 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001747 struct lyxml_elem *child, *node, *next, *next2;
1748 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001749 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001750
Michal Vasko53b7da02018-02-13 15:28:42 +01001751 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001752
Michal Vasko53b7da02018-02-13 15:28:42 +01001753 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001754 goto error;
1755 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001756 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001757
Radek Krejci07d0fb92017-01-13 14:11:05 +01001758 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001759 goto error;
1760 }
1761
Radek Krejcie534c132016-11-23 13:32:31 +01001762 LY_TREE_FOR_SAFE(yin->child, next, node) {
1763 if (strcmp(node->ns->value, LY_NSYIN)) {
1764 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001765 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001766 c_ext++;
1767 } else if (!strcmp(node->name, "argument")) {
1768 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001769 GETVAL(ctx, value, node, "name");
1770 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001771 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001772 goto error;
1773 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001774
Radek Krejcia1a6b762016-11-14 09:53:38 +09001775 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001776 LY_TREE_FOR_SAFE(node->child, next2, child) {
1777 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001778 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001779 if (ly_strequal(value, "true", 0)) {
1780 ext->flags |= LYS_YINELEM;
1781 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001782
Radek Krejci8d6b7422017-02-03 14:42:13 +01001783 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001784 goto error;
1785 }
Radek Krejcie534c132016-11-23 13:32:31 +01001786 } else if (child->ns) {
1787 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001788 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001789 goto error;
1790 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001791 }
1792
Michal Vasko53b7da02018-02-13 15:28:42 +01001793 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001794 } else {
1795 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001796 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001797 goto error;
1798 }
1799 }
1800
1801 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001802 /* some extensions may be already present from the substatements */
1803 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001804 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001805 ext->ext = reallocated;
1806
1807 /* init memory */
1808 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1809
1810 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001811 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001812 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 +01001813 ext->ext_size++;
1814 if (rc) {
1815 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001816 }
1817 }
1818 }
1819
Radek Krejci0a498f82017-01-04 16:24:15 +01001820 /* search for plugin */
1821 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 +09001822
1823 return EXIT_SUCCESS;
1824
1825error:
1826 return EXIT_FAILURE;
1827}
1828
Michal Vasko0d343d12015-08-24 14:57:36 +02001829/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001830static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001831fill_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 +02001832{
Michal Vasko53b7da02018-02-13 15:28:42 +01001833 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001834 const char *value;
1835 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001836 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001837 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001838
Michal Vasko53b7da02018-02-13 15:28:42 +01001839 GETVAL(ctx, value, yin, "name");
1840 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001841 goto error;
1842 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001843 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001844 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001845
Radek Krejci07d0fb92017-01-13 14:11:05 +01001846 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001847 goto error;
1848 }
1849
Radek Krejcie534c132016-11-23 13:32:31 +01001850 LY_TREE_FOR(yin->child, child) {
1851 if (strcmp(child->ns->value, LY_NSYIN)) {
1852 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001853 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001854 c_ext++;
1855 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001856 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001857 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001858 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001859 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001860 goto error;
1861 }
1862 }
1863
Radek Krejcie534c132016-11-23 13:32:31 +01001864 if (c_ftrs) {
1865 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001866 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001867 }
Radek Krejcie534c132016-11-23 13:32:31 +01001868 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001869 /* some extensions may be already present from the substatements */
1870 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001871 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001872 f->ext = reallocated;
1873
1874 /* init memory */
1875 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001876 }
1877
Radek Krejcie534c132016-11-23 13:32:31 +01001878 LY_TREE_FOR_SAFE(yin->child, next, child) {
1879 if (strcmp(child->ns->value, LY_NSYIN)) {
1880 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001881 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 +01001882 f->ext_size++;
1883 if (ret) {
1884 goto error;
1885 }
1886 } else { /* if-feature */
1887 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1888 f->iffeature_size++;
1889 if (ret) {
1890 goto error;
1891 }
1892 }
1893 }
1894
Radek Krejcic79c6b12016-07-26 15:11:49 +02001895 /* check for circular dependencies */
1896 if (f->iffeature_size) {
1897 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1898 goto error;
1899 }
1900 }
1901
Radek Krejci3cf9e222015-06-18 11:37:50 +02001902 return EXIT_SUCCESS;
1903
1904error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001905 return EXIT_FAILURE;
1906}
1907
Michal Vasko0d343d12015-08-24 14:57:36 +02001908/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001909static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001910fill_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 +02001911{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001912 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001913
Michal Vasko53b7da02018-02-13 15:28:42 +01001914 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001915 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001916 if (!must->expr) {
1917 goto error;
1918 }
Radek Krejci800af702015-06-02 13:46:01 +02001919
Radek Krejciaa9c5202017-02-15 16:10:14 +01001920 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001921
Michal Vasko77dc5652016-02-15 12:32:42 +01001922error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001923 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001924}
1925
Radek Krejci581ce772015-11-10 17:22:40 +01001926static int
Radek Krejci7417a082017-02-16 11:07:59 +01001927fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1928 struct unres_schema *unres)
1929{
Michal Vasko53b7da02018-02-13 15:28:42 +01001930 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001931 struct lyxml_elem *next, *child;
1932 const char *value;
1933
Michal Vasko53b7da02018-02-13 15:28:42 +01001934 GETVAL(ctx, value, yin, "date");
1935 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001936 goto error;
1937 }
1938 memcpy(rev->date, value, LY_REV_SIZE - 1);
1939
1940 LY_TREE_FOR_SAFE(yin->child, next, child) {
1941 if (!child->ns) {
1942 /* garbage */
1943 continue;
1944 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1945 /* possible extension instance */
1946 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1947 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1948 goto error;
1949 }
1950 } else if (!strcmp(child->name, "description")) {
1951 if (rev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001952 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001953 goto error;
1954 }
1955 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1956 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1957 goto error;
1958 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001959 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001960 if (!rev->dsc) {
1961 goto error;
1962 }
1963 } else if (!strcmp(child->name, "reference")) {
1964 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001965 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001966 goto error;
1967 }
1968 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1969 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1970 goto error;
1971 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001972 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001973 if (!rev->ref) {
1974 goto error;
1975 }
1976 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001977 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001978 goto error;
1979 }
1980 }
1981
1982 return EXIT_SUCCESS;
1983
1984error:
1985 return EXIT_FAILURE;
1986}
1987
1988static int
Michal Vasko88c29542015-11-27 14:57:53 +01001989fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1990 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001991{
Michal Vasko53b7da02018-02-13 15:28:42 +01001992 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02001993 int i, j, ret = EXIT_FAILURE;
1994 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02001995 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001996 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001997
1998 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01001999 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01002000
2001 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002002 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01002003 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002004 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002005 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02002006 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01002007 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01002008 while (isspace(*vaux)) {
2009 vaux++;
2010 }
2011 }
2012 unique->expr_size++;
2013 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002014 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002015
2016 for (i = 0; i < unique->expr_size; i++) {
2017 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02002018 if (vaux) {
2019 c = *vaux;
2020 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01002021 }
2022
2023 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002024 unique->expr[i] = transform_schema2json(module, value);
2025 if (vaux) {
2026 *vaux = c;
2027 }
Radek Krejci581ce772015-11-10 17:22:40 +01002028
2029 /* check that the expression does not repeat */
2030 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002031 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002032 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
2033 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01002034 goto error;
2035 }
2036 }
2037
2038 /* try to resolve leaf */
2039 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002040 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01002041 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02002042 unique_info->list = parent;
2043 unique_info->expr = unique->expr[i];
2044 unique_info->trg_type = &unique->trg_type;
2045 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02002046 goto error;
2047 }
Radek Krejci581ce772015-11-10 17:22:40 +01002048 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002049 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002050 goto error;
2051 }
2052 }
2053
2054 /* move to next token */
2055 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002056 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002057 value++;
2058 }
2059 }
2060
Radek Krejci1a9c3612017-04-24 14:49:43 +02002061 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002062
2063error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002064 free(start);
2065 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002066}
2067
Michal Vasko0d343d12015-08-24 14:57:36 +02002068/* logs directly
2069 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002070 * type: 0 - min, 1 - max
2071 */
2072static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002073deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002074{
2075 const char *value;
2076 char *endptr;
2077 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002078 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002079 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002080
Michal Vaskof7e57d52016-03-07 11:31:09 +01002081 /* del min/max is forbidden */
2082 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002083 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002084 goto error;
2085 }
2086
Radek Krejcieb00f512015-07-01 16:44:58 +02002087 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002088 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002089 max = &((struct lys_node_leaflist *)target)->max;
2090 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002091 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002092 max = &((struct lys_node_list *)target)->max;
2093 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002094 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002095 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2096 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002097 goto error;
2098 }
2099
Michal Vasko53b7da02018-02-13 15:28:42 +01002100 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002101 while (isspace(value[0])) {
2102 value++;
2103 }
2104
Radek Krejci0d7b2472016-02-12 11:11:03 +01002105 if (type && !strcmp(value, "unbounded")) {
2106 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002107 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002108 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002109 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002110 /* convert it to uint32_t */
2111 errno = 0;
2112 endptr = NULL;
2113 val = strtoul(value, &endptr, 10);
2114 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002115 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002116 goto error;
2117 }
2118 if (type) {
2119 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002120 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002121 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002122 } else {
2123 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002124 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002125 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002126 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002127 }
2128
2129 if (d->mod == LY_DEVIATE_ADD) {
2130 /* check that there is no current value */
2131 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002132 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2133 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002134 goto error;
2135 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002136 } else if (d->mod == LY_DEVIATE_RPL) {
2137 /* unfortunately, there is no way to check reliably that there
2138 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002139 }
2140
Michal Vaskof7e57d52016-03-07 11:31:09 +01002141 /* add (already checked) and replace */
2142 /* set new value specified in deviation */
2143 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002144
Pavol Vican09adcc32016-08-25 10:51:36 +02002145 /* check min-elements is smaller than max-elements */
2146 if (*max && *min > *max) {
2147 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002148 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2149 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002150 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002151 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2152 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002153 }
2154 goto error;
2155 }
2156
Radek Krejcieb00f512015-07-01 16:44:58 +02002157 return EXIT_SUCCESS;
2158
2159error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002160 return EXIT_FAILURE;
2161}
2162
Michal Vasko0d343d12015-08-24 14:57:36 +02002163/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002164static int
Michal Vasko88c29542015-11-27 14:57:53 +01002165fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2166 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002167{
2168 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002169 struct lyxml_elem *next, *next2, *child, *develem;
2170 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002171 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002172 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002173 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002174 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002175 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002176 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002177 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002178 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002179 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002180 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002181 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002182 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002183 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002184 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002185 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002186 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002187 void *reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002188
Michal Vasko53b7da02018-02-13 15:28:42 +01002189 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002190 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002191 if (!dev->target_name) {
2192 goto error;
2193 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002194
2195 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002196 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2197 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002198 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002199 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002200 goto error;
2201 }
Michal Vasko50576712017-07-28 12:28:33 +02002202 dev_target = set->set.s[0];
2203 ly_set_free(set);
2204
Radek Krejcic4283442016-04-22 09:19:27 +02002205 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002206 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2207 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002208 goto error;
2209 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002210
2211 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002212 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002213 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002214 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002215 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002216 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2217 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002218 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002219 c_ext++;
2220 continue;
2221 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002222 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002223 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002224 goto error;
2225 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002226 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002227 goto error;
2228 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002229 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 if (!dev->dsc) {
2231 goto error;
2232 }
2233 } else if (!strcmp(child->name, "reference")) {
2234 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002235 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 goto error;
2237 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002238 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002239 goto error;
2240 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002241 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002242 if (!dev->ref) {
2243 goto error;
2244 }
2245 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002246 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002247 c_dev++;
2248
Michal Vasko345da0a2015-12-02 10:35:55 +01002249 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002250 * further processed later
2251 */
2252 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002253
Radek Krejcieb00f512015-07-01 16:44:58 +02002254 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002255 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002256 goto error;
2257 }
2258
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002259 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002260 }
2261
2262 if (c_dev) {
2263 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002264 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002265 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002266 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002267 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002268 }
Radek Krejcie534c132016-11-23 13:32:31 +01002269 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002270 /* some extensions may be already present from the substatements */
2271 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002272 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002273 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002274
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002275 /* init memory */
2276 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2277 }
Radek Krejcie534c132016-11-23 13:32:31 +01002278
2279 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2280 if (strcmp(develem->ns->value, LY_NSYIN)) {
2281 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002282 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 +01002283 dev->ext_size++;
2284 if (rc) {
2285 goto error;
2286 }
2287 continue;
2288 }
2289
2290 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002291 /* init */
2292 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002293 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002294 c_must = 0;
2295 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002296 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002297 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002298
2299 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002300 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002301 if (!strcmp(value, "not-supported")) {
2302 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002303 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002304 * not-supported deviation must be the only deviation of the target
2305 */
2306 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002307 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2308 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002309 goto error;
2310 }
2311
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002312 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002313 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2314 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2315 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002316 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2317 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002318 goto error;
2319 }
2320 }
2321 }
Radek Krejci5b917642015-07-02 09:03:13 +02002322
Michal Vaskoff006c12016-02-17 11:15:19 +01002323 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002324 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002325 lys_node_unlink(dev_target);
Michal Vaskoa1074a52018-01-03 12:18:53 +01002326 if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01002327 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2328 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2329 * path), so we need to remember the augment as an addition */
Michal Vaskoa1074a52018-01-03 12:18:53 +01002330 /* remember uses parent so we can reconnect to it */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002331 dev_target->parent = parent;
2332 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002333 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002334
Radek Krejcieb00f512015-07-01 16:44:58 +02002335 } else if (!strcmp(value, "add")) {
2336 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2337 } else if (!strcmp(value, "replace")) {
2338 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2339 } else if (!strcmp(value, "delete")) {
2340 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2341 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002342 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002343 goto error;
2344 }
2345 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002346 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002347
Michal Vaskoff006c12016-02-17 11:15:19 +01002348 /* store a shallow copy of the original node */
2349 if (!dev->orig_node) {
2350 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002351 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002352 /* just to be safe */
2353 if (tmp_unres.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002354 LOGINT(ctx);
Michal Vaskoff006c12016-02-17 11:15:19 +01002355 goto error;
2356 }
2357 }
2358
Radek Krejcieb00f512015-07-01 16:44:58 +02002359 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002360 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002361 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002362 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002363 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002364 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002365 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2366 /* extensions */
Michal Vasko53b7da02018-02-13 15:28:42 +01002367 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, d->ext_size, "extensions", "deviate", error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002368 c_ext++;
2369 } else if (d->mod == LY_DEVIATE_NO) {
2370 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002371 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002372 goto error;
2373 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002374 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002375 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002376 goto error;
2377 }
2378
2379 /* for we deviate from RFC 6020 and allow config property even it is/is not
2380 * specified in the target explicitly since config property inherits. So we expect
2381 * that config is specified in every node. But for delete, we check that the value
2382 * is the same as here in deviation
2383 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002384 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002385 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002386 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002387 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002388 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002389 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002390 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002391 goto error;
2392 }
2393
2394 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002395 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002396 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002397 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002398 } else { /* add and replace are the same in this case */
2399 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002400 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002401
2402 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002403 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002404 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002405
Radek Krejci8d6b7422017-02-03 14:42:13 +01002406 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002407 goto error;
2408 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002409 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002410 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002411 goto error;
2412 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002413 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002414 c_dflt++;
2415
2416 /* check target node type */
2417 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002418 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2419 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002420 goto error;
2421 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002422 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2423 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002424 goto error;
2425 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002426 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2427 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002428 goto error;
2429 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002430
Radek Krejcid5a5c282016-08-15 15:38:08 +02002431 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2432 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002433
Radek Krejcieb00f512015-07-01 16:44:58 +02002434 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002435 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002436 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002437 goto error;
2438 }
2439
2440 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002441 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002442 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2443 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002444 goto error;
2445 }
2446
Michal Vasko53b7da02018-02-13 15:28:42 +01002447 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002448 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002449 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002450 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002451 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002452 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002453 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002454 goto error;
2455 }
2456
2457 if (d->mod == LY_DEVIATE_ADD) {
2458 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002459 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002460 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2461 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002462 goto error;
2463 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002464
Radek Krejci841ec082016-04-05 13:05:17 +02002465 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002466 if (d->flags & LYS_MAND_TRUE) {
2467 if (dev_target->nodetype == LYS_CHOICE) {
2468 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002469 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2470 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002471 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2472 goto error;
2473 }
2474 } else if (dev_target->nodetype == LYS_LEAF) {
2475 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002476 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2477 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002478 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2479 goto error;
2480 }
2481 }
Radek Krejci841ec082016-04-05 13:05:17 +02002482 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002483
Michal Vasko21be1b32016-03-07 12:31:34 +01002484 dev_target->flags |= d->flags & LYS_MAND_MASK;
2485 } else if (d->mod == LY_DEVIATE_RPL) {
2486 /* check that there was a value before */
2487 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002488 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2489 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002490 goto error;
2491 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002492
Michal Vasko21be1b32016-03-07 12:31:34 +01002493 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002494 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002495 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002496 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002497 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002498 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002499 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002500
2501 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2502 for (parent = dev_target->parent;
2503 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2504 parent = parent->parent) {
2505 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2506 /* stop also on presence containers */
2507 break;
2508 }
2509 }
2510 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2511 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2512 if (lyp_check_mandatory_choice(parent)) {
2513 goto error;
2514 }
2515 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002516
Radek Krejci8d6b7422017-02-03 14:42:13 +01002517 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002518 goto error;
2519 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002520 } else if (!strcmp(child->name, "min-elements")) {
2521 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002522 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002523 goto error;
2524 }
2525 f_min = 1;
2526
Michal Vasko60f4b452016-02-12 11:02:55 +01002527 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002528 goto error;
2529 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002530 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002531 goto error;
2532 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002533 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002534 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002535 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002536 goto error;
2537 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002538 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002539
Michal Vasko60f4b452016-02-12 11:02:55 +01002540 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002541 goto error;
2542 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002543 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002544 goto error;
2545 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002546 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002547 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002548 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002549 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002550 continue;
2551 } else if (!strcmp(child->name, "type")) {
2552 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002553 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002554 goto error;
2555 }
2556
Michal Vaskof7e57d52016-03-07 11:31:09 +01002557 /* add, del type is forbidden */
2558 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002559 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002560 goto error;
2561 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002562 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002563 goto error;
2564 }
2565
Radek Krejcieb00f512015-07-01 16:44:58 +02002566 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002567 if (dev_target->nodetype == LYS_LEAF) {
2568 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002569 if (((struct lys_node_leaf *)dev_target)->dflt) {
2570 ly_set_add(dflt_check, dev_target, 0);
2571 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002572 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2573 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002574 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2575 ly_set_add(dflt_check, dev_target, 0);
2576 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002577 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002578 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2579 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002580 goto error;
2581 }
2582
Radek Krejcieb00f512015-07-01 16:44:58 +02002583 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002584 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002585 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002586 /* HACK for unres */
2587 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002588 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002589 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002590 goto error;
2591 }
2592 d->type = t;
2593 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002594 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNIQUE, c_uniq, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002595 goto error;
2596 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002597 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002598 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002599 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002600 continue;
2601 } else if (!strcmp(child->name, "units")) {
2602 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002603 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002604 goto error;
2605 }
2606
2607 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002608 if (dev_target->nodetype == LYS_LEAFLIST) {
2609 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2610 } else if (dev_target->nodetype == LYS_LEAF) {
2611 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002612 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002613 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2614 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002615 goto error;
2616 }
2617
2618 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002619 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002620 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002621
2622 /* apply to target */
2623 if (d->mod == LY_DEVIATE_ADD) {
2624 /* check that there is no current value */
2625 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002626 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2627 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002628 goto error;
2629 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002630
Michal Vasko21be1b32016-03-07 12:31:34 +01002631 *stritem = lydict_insert(ctx, value, 0);
2632 } else if (d->mod == LY_DEVIATE_RPL) {
2633 /* check that there was a value before */
2634 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002635 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2636 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002637 goto error;
2638 }
2639
2640 lydict_remove(ctx, *stritem);
2641 *stritem = lydict_insert(ctx, value, 0);
2642 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002643 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002644 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002645 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2646 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002647 goto error;
2648 }
2649 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002650 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002651 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002652
2653 /* remove its extensions */
2654 j = -1;
2655 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2656 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2657 --j;
2658 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002659 }
2660
Radek Krejci8d6b7422017-02-03 14:42:13 +01002661 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002662 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002663 }
2664 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002665 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002666 goto error;
2667 }
2668
Michal Vasko88c29542015-11-27 14:57:53 +01002669 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002670 }
2671
2672 if (c_must) {
2673 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002674 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002675 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002676 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2677 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002678 break;
Radek Krejci76512572015-08-04 09:47:08 +02002679 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002680 trg_must = &((struct lys_node_container *)dev_target)->must;
2681 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002682 break;
Radek Krejci76512572015-08-04 09:47:08 +02002683 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002684 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2685 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002686 break;
Radek Krejci76512572015-08-04 09:47:08 +02002687 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002688 trg_must = &((struct lys_node_list *)dev_target)->must;
2689 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002690 break;
Radek Krejci76512572015-08-04 09:47:08 +02002691 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002692 case LYS_ANYDATA:
2693 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2694 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002695 break;
2696 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002697 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2698 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002699 goto error;
2700 }
2701
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002702 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002703
Radek Krejcieb00f512015-07-01 16:44:58 +02002704 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002705 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002706 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002707 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002708 } else if (d->mod == LY_DEVIATE_ADD) {
2709 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002710 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01002711 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002712 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002713 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002714 d->must_size = c_must;
2715 } else { /* LY_DEVIATE_DEL */
2716 d->must = calloc(c_must, sizeof *d->must);
2717 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002718 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002719 }
2720 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002721 /* replace unique is forbidden */
2722 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002723 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002724 goto error;
2725 }
2726
Radek Krejcieb00f512015-07-01 16:44:58 +02002727 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002728 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002729 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2730 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002731 goto error;
2732 }
2733
Michal Vasko60f4b452016-02-12 11:02:55 +01002734 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002735 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002736 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002737 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002738 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002739 list->unique = d->unique;
2740 d->unique = &list->unique[list->unique_size];
2741 d->unique_size = c_uniq;
2742 } else { /* LY_DEVIATE_DEL */
2743 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002744 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002745 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002746 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002747 if (c_dflt) {
2748 if (d->mod == LY_DEVIATE_ADD) {
2749 /* check that there is no current value */
2750 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2751 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002752 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2753 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002754 goto error;
2755 }
2756
2757 /* check collision with mandatory/min-elements */
2758 if ((dev_target->flags & LYS_MAND_TRUE) ||
2759 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002760 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2761 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002762 "Adding the \"default\" statement is forbidden on %s statement.",
2763 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2764 goto error;
2765 }
2766 } else if (d->mod == LY_DEVIATE_RPL) {
2767 /* check that there was a value before */
2768 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2769 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002770 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2771 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002772 goto error;
2773 }
2774 }
2775
2776 if (dev_target->nodetype == LYS_LEAFLIST) {
2777 /* reallocate default list in the target */
2778 llist = (struct lys_node_leaflist *)dev_target;
2779 if (d->mod == LY_DEVIATE_ADD) {
2780 /* reallocate (enlarge) the unique array of the target */
2781 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002782 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002783 } else if (d->mod == LY_DEVIATE_RPL) {
2784 /* reallocate (replace) the unique array of the target */
2785 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002786 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002787 }
2788 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2789 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002790 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002791 }
2792 }
2793 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002794 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002795 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002796 if (c_ext) {
2797 /* some extensions may be already present from the substatements */
2798 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002799 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002800 d->ext = reallocated;
2801
2802 /* init memory */
2803 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2804 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002805
2806 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002807 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2808 if (strcmp(child->ns->value, LY_NSYIN)) {
2809 /* extension */
2810 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2811 goto error;
2812 }
2813 d->ext_size++;
2814 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002815 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002816 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002817 goto error;
2818 }
2819
2820 /* find must to delete, we are ok with just matching conditions */
2821 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002822 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002823 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002824 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002825 /* ... and maintain the array */
2826 (*trg_must_size)--;
2827 if (i != *trg_must_size) {
2828 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2829 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2830 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2831 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2832 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2833 }
2834 if (!(*trg_must_size)) {
2835 free(*trg_must);
2836 *trg_must = NULL;
2837 } else {
2838 (*trg_must)[*trg_must_size].expr = NULL;
2839 (*trg_must)[*trg_must_size].dsc = NULL;
2840 (*trg_must)[*trg_must_size].ref = NULL;
2841 (*trg_must)[*trg_must_size].eapptag = NULL;
2842 (*trg_must)[*trg_must_size].emsg = NULL;
2843 }
2844
2845 i = -1; /* set match flag */
2846 break;
2847 }
2848 }
2849 d->must_size++;
2850 if (i != -1) {
2851 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002852 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002853 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002854 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002855 goto error;
2856 }
2857 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002858 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002859 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002860 goto error;
2861 }
2862 (*trg_must_size)++;
2863 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002864
2865 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002866 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2867 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002868 goto error;
2869 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002870 } else if (!strcmp(child->name, "unique")) {
2871 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002872 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002873 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002874 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002875 goto error;
2876 }
2877
2878 /* find unique structures to delete */
2879 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002880 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002881 continue;
2882 }
2883
Radek Krejci581ce772015-11-10 17:22:40 +01002884 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002885 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002886 break;
2887 }
2888 }
2889
Radek Krejci581ce772015-11-10 17:22:40 +01002890 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002891 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002892 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002893 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002894 }
2895 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002896 /* ... and maintain the array */
2897 list->unique_size--;
2898 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002899 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2900 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002901 }
2902
2903 if (!list->unique_size) {
2904 free(list->unique);
2905 list->unique = NULL;
2906 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002907 list->unique[list->unique_size].expr_size = 0;
2908 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002909 }
2910
Radek Krejci6bd2c022017-02-01 15:04:49 +01002911 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002912 i = -1; /* set match flag */
2913 break;
2914 }
2915 }
2916
2917 d->unique_size++;
2918 if (i != -1) {
2919 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002920 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2921 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002922 goto error;
2923 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002924
2925 /* remove extensions of this unique instance from the target node */
2926 j = -1;
2927 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE)) != -1) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002928 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002929 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2930 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002931 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002932 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002933 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002934 }
2935 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002936 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002937 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002938 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002939 list->unique_size++;
2940 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002941 goto error;
2942 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002943 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002944 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002945 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002946 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002947 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002948
2949 if (dev_target->nodetype == LYS_CHOICE) {
2950 choice = (struct lys_node_choice *)dev_target;
2951 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2952 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002953 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002954 goto error;
2955 }
2956 if (d->mod == LY_DEVIATE_DEL) {
2957 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002958 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2959 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002960 goto error;
2961 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002962 choice->dflt = NULL;
2963 /* remove extensions of this default instance from the target node */
2964 j = -1;
2965 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2966 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2967 --j;
2968 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002969 } else { /* add or replace */
2970 choice->dflt = node;
2971 if (!choice->dflt) {
2972 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002973 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002974 goto error;
2975 }
2976 }
2977 } else if (dev_target->nodetype == LYS_LEAF) {
2978 leaf = (struct lys_node_leaf *)dev_target;
2979 if (d->mod == LY_DEVIATE_DEL) {
2980 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002981 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2982 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002983 goto error;
2984 }
2985 /* remove value */
2986 lydict_remove(ctx, leaf->dflt);
2987 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002988 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002989
2990 /* remove extensions of this default instance from the target node */
2991 j = -1;
2992 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2993 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2994 --j;
2995 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002996 } else { /* add (already checked) and replace */
2997 /* remove value */
2998 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002999 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003000
3001 /* set new value */
3002 leaf->dflt = lydict_insert(ctx, value, u);
3003
Radek Krejcibd117f02016-11-04 16:28:08 +01003004 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02003005 ly_set_add(dflt_check, dev_target, 0);
3006 }
3007 } else { /* LYS_LEAFLIST */
3008 llist = (struct lys_node_leaflist *)dev_target;
3009 if (d->mod == LY_DEVIATE_DEL) {
3010 /* find and remove the value in target list */
3011 for (i = 0; i < llist->dflt_size; i++) {
3012 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
3013 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01003014 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003015 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003016
3017 /* remove extensions of this default instance from the target node */
3018 j = -1;
3019 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
Radek Krejcifebdad72017-02-06 11:35:51 +01003020 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003021 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3022 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003023 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003024 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003025 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003026 }
3027 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003028 break;
3029 }
3030 }
3031 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003032 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3033 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003034 goto error;
3035 }
3036 } else {
3037 /* add or replace, anyway we place items into the deviate's list
3038 which propagates to the target */
3039 /* we just want to check that the value isn't already in the list */
3040 for (i = 0; i < llist->dflt_size; i++) {
3041 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003042 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3043 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003044 goto error;
3045 }
3046 }
3047 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003048 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003049
3050 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3051 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003052 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003053 }
3054 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003055 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003056 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003057
3058 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3059 /* consolidate the final list in the target after removing items from it */
3060 llist = (struct lys_node_leaflist *)dev_target;
3061 for (i = j = 0; j < llist->dflt_size; j++) {
3062 llist->dflt[i] = llist->dflt[j];
3063 if (llist->dflt[i]) {
3064 i++;
3065 }
3066 }
3067 llist->dflt_size = i + 1;
3068 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003069 }
3070
Michal Vasko43a1feb2016-03-07 12:03:02 +01003071 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003072 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003073 for (u = 0; u < dflt_check->number; ++u) {
3074 value = NULL;
3075 rc = EXIT_SUCCESS;
3076 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3077 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3078 value = leaf->dflt;
3079 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3080 } else { /* LYS_LEAFLIST */
3081 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3082 for (j = 0; j < llist->dflt_size; j++) {
3083 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3084 (struct lys_node *)(&llist->dflt[j]));
3085 if (rc == -1) {
3086 value = llist->dflt[j];
3087 break;
3088 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003089 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003090
Michal Vasko15a43372017-09-25 14:12:42 +02003091 }
3092 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003093 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3094 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003095 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3096 dev->target_name);
3097 goto error;
3098 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003099 }
3100 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003101
Radek Krejci27fe55e2016-09-13 17:13:35 +02003102 /* mark all the affected modules as deviated and implemented */
3103 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3104 mod = lys_node_module(parent);
3105 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003106 mod->deviated = 1; /* main module */
3107 parent->module->deviated = 1; /* possible submodule */
Radek Krejci2bb5be72017-02-27 13:07:25 +01003108 if (lys_set_implemented(mod)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003109 LOGERR(ctx, ly_errno, "Setting the deviated module \"%s\" implemented failed.", mod->name);
Radek Krejci2bb5be72017-02-27 13:07:25 +01003110 goto error;
3111 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003112 }
3113 }
3114
Radek Krejcid5a5c282016-08-15 15:38:08 +02003115 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003116 return EXIT_SUCCESS;
3117
3118error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003119 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003120 return EXIT_FAILURE;
3121}
3122
Michal Vasko0d343d12015-08-24 14:57:36 +02003123/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003124static int
Radek Krejcib8048692015-08-05 13:36:34 +02003125fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003126 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003127{
Michal Vasko53b7da02018-02-13 15:28:42 +01003128 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003130 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003131 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003132 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003133 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003134
Michal Vasko591e0b22015-08-13 13:53:43 +02003135 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003136 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003137 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003138 if (!aug->target_name) {
3139 goto error;
3140 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003141 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003142
Radek Krejci07d0fb92017-01-13 14:11:05 +01003143 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003144 goto error;
3145 }
3146
Radek Krejcie534c132016-11-23 13:32:31 +01003147 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3148 if (strcmp(sub->ns->value, LY_NSYIN)) {
3149 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003150 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003151 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003152 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003153 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003154 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003155 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003156 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003157 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003158 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003159 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003160 goto error;
3161 }
3162
Radek Krejci5323b492017-01-16 15:40:11 +01003163 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003164 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003165 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003166 goto error;
3167 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003168 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003169 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003170
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003171 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003172 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003173 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003174 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003175 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003176 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003177 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003178 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003179 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003180 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003181 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003182 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003183 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003184 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003185 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003186 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003187 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003188 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003189 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003190 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003191 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003192 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003193 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003194 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003195 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003196 goto error;
3197 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003198
Radek Krejci1d82ef62015-08-07 14:44:40 +02003199 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003200 goto error;
3201 }
3202
Radek Krejci1d82ef62015-08-07 14:44:40 +02003203 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003204 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003205 }
3206
Radek Krejcie534c132016-11-23 13:32:31 +01003207 if (c_ftrs) {
3208 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003209 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003210 }
Radek Krejcie534c132016-11-23 13:32:31 +01003211 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003212 /* some extensions may be already present from the substatements */
3213 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003214 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003215 aug->ext = reallocated;
3216
3217 /* init memory */
3218 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003219 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003220
Radek Krejcie534c132016-11-23 13:32:31 +01003221 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3222 if (strcmp(sub->ns->value, LY_NSYIN)) {
3223 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003224 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 +01003225 aug->ext_size++;
3226 if (ret) {
3227 goto error;
3228 }
3229 } else if (!strcmp(sub->name, "if-feature")) {
3230 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003231 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003232 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003233 goto error;
3234 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003235 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003236 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003237 }
3238
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003239 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003240 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003241 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003242 * when the uses does and cannot be resolved now for sure
3243 * (the grouping was not yet copied into uses).
3244 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003245 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003246 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003247 goto error;
3248 }
Michal Vasko49291b32015-08-06 09:49:41 +02003249 }
Radek Krejci106efc02015-06-10 14:36:27 +02003250
Michal Vasko508a50d2016-09-07 14:50:33 +02003251 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003252 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003253 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003254 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003255 goto error;
3256 }
3257 } else {
3258 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3259 goto error;
3260 }
3261 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003262 }
3263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003265
3266error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003268}
3269
Michal Vasko0d343d12015-08-24 14:57:36 +02003270/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003272fill_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 +02003273{
Michal Vasko53b7da02018-02-13 15:28:42 +01003274 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003275 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003276 struct lyxml_elem *sub, *next;
3277 const char *value;
3278 char *endptr;
3279 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003280 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 int r;
3282 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003283 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003284
Radek Krejci363bd4a2016-07-29 14:30:20 +02003285 assert(uses);
3286 module = uses->module; /* shorthand */
3287
Michal Vasko53b7da02018-02-13 15:28:42 +01003288 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003289 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003290 if (!rfn->target_name) {
3291 goto error;
3292 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003295 if (!sub->ns) {
3296 /* garbage */
3297 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003298 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003299 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003300 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003301 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003302
Radek Krejci411b1bf2017-01-23 16:40:05 +01003303 } else if (!strcmp(sub->name, "description")) {
3304 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003305 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003306 goto error;
3307 }
3308
Radek Krejci8d6b7422017-02-03 14:42:13 +01003309 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003310 goto error;
3311 }
3312
Michal Vasko53b7da02018-02-13 15:28:42 +01003313 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003314 if (!rfn->dsc) {
3315 goto error;
3316 }
3317 } else if (!strcmp(sub->name, "reference")) {
3318 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003319 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003320 goto error;
3321 }
3322
Radek Krejci8d6b7422017-02-03 14:42:13 +01003323 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003324 goto error;
3325 }
3326
Michal Vasko53b7da02018-02-13 15:28:42 +01003327 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003328 if (!rfn->ref) {
3329 goto error;
3330 }
3331 } else if (!strcmp(sub->name, "config")) {
3332 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003333 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003334 goto error;
3335 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003336 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003337 if (!strcmp(value, "false")) {
3338 rfn->flags |= LYS_CONFIG_R;
3339 } else if (!strcmp(value, "true")) {
3340 rfn->flags |= LYS_CONFIG_W;
3341 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003342 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003343 goto error;
3344 }
3345 rfn->flags |= LYS_CONFIG_SET;
3346
Radek Krejci8d6b7422017-02-03 14:42:13 +01003347 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003348 goto error;
3349 }
Radek Krejcie534c132016-11-23 13:32:31 +01003350 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003351 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 /* check possibility of statements combination */
3354 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003355 if (c_dflt) {
3356 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003357 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003358 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003359 goto error;
3360 }
Radek Krejci200bf712016-08-16 17:11:04 +02003361 rfn->target_type &= LYS_LEAFLIST;
3362 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003363 if (module->version < 2) {
3364 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3365 } else {
3366 /* YANG 1.1 */
3367 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3368 }
Radek Krejci200bf712016-08-16 17:11:04 +02003369 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003370 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003371 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3372 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 goto error;
3374 }
3375 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003376 if (module->version < 2) {
3377 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3378 } else {
3379 /* YANG 1.1 */
3380 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3381 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003383
Michal Vasko53b7da02018-02-13 15:28:42 +01003384 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003385 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003386 goto error;
3387 }
Radek Krejci200bf712016-08-16 17:11:04 +02003388 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003389 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 } else if (!strcmp(sub->name, "mandatory")) {
3391 /* leaf, choice or anyxml */
3392 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003393 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003394 goto error;
3395 }
3396 /* just checking the flags in leaf is not sufficient, we would allow
3397 * multiple mandatory statements with the "false" value
3398 */
3399 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 /* check possibility of statements combination */
3402 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003403 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003405 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3406 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 goto error;
3408 }
3409 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003410 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003412
Michal Vasko53b7da02018-02-13 15:28:42 +01003413 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003415 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003417 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003419 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 goto error;
3421 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003422 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003423 goto error;
3424 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 } else if (!strcmp(sub->name, "min-elements")) {
3426 /* list or leaf-list */
3427 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003428 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 goto error;
3430 }
3431 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 /* check possibility of statements combination */
3434 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003435 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003437 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3438 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 goto error;
3440 }
3441 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003442 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003444
Michal Vasko53b7da02018-02-13 15:28:42 +01003445 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 while (isspace(value[0])) {
3447 value++;
3448 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 /* convert it to uint32_t */
3451 errno = 0;
3452 endptr = NULL;
3453 val = strtoul(value, &endptr, 10);
3454 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003455 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
3458 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003459 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003460
Radek Krejci8d6b7422017-02-03 14:42:13 +01003461 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003462 goto error;
3463 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 } else if (!strcmp(sub->name, "max-elements")) {
3465 /* list or leaf-list */
3466 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003467 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003468 goto error;
3469 }
3470 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 /* check possibility of statements combination */
3473 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003474 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003476 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3477 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 goto error;
3479 }
3480 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003481 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003483
Michal Vasko53b7da02018-02-13 15:28:42 +01003484 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 while (isspace(value[0])) {
3486 value++;
3487 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003488
Radek Krejci0d7b2472016-02-12 11:11:03 +01003489 if (!strcmp(value, "unbounded")) {
3490 rfn->mod.list.max = 0;
3491 } else {
3492 /* convert it to uint32_t */
3493 errno = 0;
3494 endptr = NULL;
3495 val = strtoul(value, &endptr, 10);
3496 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003497 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003498 goto error;
3499 }
3500 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003502 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003503
Radek Krejci8d6b7422017-02-03 14:42:13 +01003504 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003505 goto error;
3506 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 } else if (!strcmp(sub->name, "presence")) {
3508 /* container */
3509 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003510 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 goto error;
3512 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 /* check possibility of statements combination */
3515 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003516 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003518 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3519 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 goto error;
3521 }
3522 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003523 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003524 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003525
Michal Vasko53b7da02018-02-13 15:28:42 +01003526 GETVAL(ctx, value, sub, "value");
3527 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003528
Radek Krejci8d6b7422017-02-03 14:42:13 +01003529 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003530 goto error;
3531 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003533 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 /* check possibility of statements combination */
3535 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003536 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003538 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3539 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 goto error;
3541 }
3542 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003543 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003545
Michal Vasko53b7da02018-02-13 15:28:42 +01003546 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003548 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003549
Radek Krejci363bd4a2016-07-29 14:30:20 +02003550 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3551 /* leaf, leaf-list, list, container or anyxml */
3552 /* check possibility of statements combination */
3553 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003554 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003555 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003556 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3557 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003558 goto error;
3559 }
3560 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003561 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003562 }
3563
Michal Vasko53b7da02018-02-13 15:28:42 +01003564 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003565 c_ftrs++;
3566 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003568 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003569 goto error;
3570 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003571
Michal Vasko53b7da02018-02-13 15:28:42 +01003572 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 /* process nodes with cardinality of 0..n */
3576 if (c_must) {
3577 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003578 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003580 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003581 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003582 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003583 }
Radek Krejci200bf712016-08-16 17:11:04 +02003584 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003585 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003586 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003587 }
Radek Krejcie534c132016-11-23 13:32:31 +01003588 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003589 /* some extensions may be already present from the substatements */
3590 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003591 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003592 rfn->ext = reallocated;
3593
3594 /* init memory */
3595 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003596 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003597
Radek Krejcie534c132016-11-23 13:32:31 +01003598 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3599 if (strcmp(sub->ns->value, LY_NSYIN)) {
3600 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003601 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 +01003602 rfn->ext_size++;
3603 if (r) {
3604 goto error;
3605 }
3606 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003607 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003608 rfn->iffeature_size++;
3609 if (r) {
3610 goto error;
3611 }
Radek Krejci200bf712016-08-16 17:11:04 +02003612 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003613 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003614 rfn->must_size++;
3615 if (r) {
3616 goto error;
3617 }
Radek Krejci200bf712016-08-16 17:11:04 +02003618 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003619 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003620
3621 /* check for duplicity */
3622 for (r = 0; r < rfn->dflt_size; r++) {
3623 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003624 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3625 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003626 goto error;
3627 }
3628 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003629 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003630 }
3631 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003632
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003634
3635error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003637}
3638
Michal Vasko0d343d12015-08-24 14:57:36 +02003639/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640static int
Radek Krejcie534c132016-11-23 13:32:31 +01003641fill_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 +02003642{
Michal Vasko53b7da02018-02-13 15:28:42 +01003643 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003644 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003645 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003646 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003647 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003648
Radek Krejcie534c132016-11-23 13:32:31 +01003649 /* init */
3650 memset(&exts, 0, sizeof exts);
3651
3652 LY_TREE_FOR_SAFE(yin->child, next, child) {
3653 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003654 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003655 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003656 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3657 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003658 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003659 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003660 lyxml_unlink_elem(ctx, child, 2);
3661 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003662 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003663 GETVAL(ctx, value, child, "value");
3664 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 goto error;
3666 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003667 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003668
Radek Krejci8d6b7422017-02-03 14:42:13 +01003669 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003670 goto error;
3671 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 } else if (!strcmp(child->name, "revision-date")) {
3673 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003674 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003675 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003676 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003677 GETVAL(ctx, value, child, "date");
3678 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 goto error;
3680 }
3681 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003682
Radek Krejci8d6b7422017-02-03 14:42:13 +01003683 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003684 goto error;
3685 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003686 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003687 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003688 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003689 goto error;
3690 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003691 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003692 goto error;
3693 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003694 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003695 if (!imp->dsc) {
3696 goto error;
3697 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003698 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003699 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003700 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003701 goto error;
3702 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003703 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003704 goto error;
3705 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003706 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003707 if (!imp->ref) {
3708 goto error;
3709 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003711 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 goto error;
3713 }
3714 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 /* check mandatory information */
3717 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003718 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003719 goto error;
3720 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003721
Radek Krejcie534c132016-11-23 13:32:31 +01003722 /* process extensions */
3723 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003724 /* some extensions may be already present from the substatements */
3725 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003726 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003727 imp->ext = reallocated;
3728
3729 /* init memory */
3730 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3731
Radek Krejcie534c132016-11-23 13:32:31 +01003732 LY_TREE_FOR_SAFE(exts.child, next, child) {
3733 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003734 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 +01003735 imp->ext_size++;
3736 if (r) {
3737 goto error;
3738 }
3739 }
3740 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003741
Michal Vasko53b7da02018-02-13 15:28:42 +01003742 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003743 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003744
3745error:
Radek Krejcie534c132016-11-23 13:32:31 +01003746 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003747 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003748 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003750}
3751
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003752/* logs directly
3753 * returns:
3754 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003755 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003756 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003758fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3759 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003760{
Michal Vasko53b7da02018-02-13 15:28:42 +01003761 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003762 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003764 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003765 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003766
Radek Krejcie534c132016-11-23 13:32:31 +01003767 /* init */
3768 memset(&exts, 0, sizeof exts);
3769
3770 LY_TREE_FOR_SAFE(yin->child, next, child) {
3771 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003772 /* garbage */
3773 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003774 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3775 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003776 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003777 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003778 lyxml_unlink_elem(ctx, child, 2);
3779 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003780 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003781 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003782 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 goto error;
3784 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003785 GETVAL(ctx, value, child, "date");
3786 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 goto error;
3788 }
3789 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003790
Radek Krejci8d6b7422017-02-03 14:42:13 +01003791 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003792 goto error;
3793 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003794 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003795 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003796 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003797 goto error;
3798 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003799 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003800 goto error;
3801 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003802 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003803 if (!inc->dsc) {
3804 goto error;
3805 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003806 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003807 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003808 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003809 goto error;
3810 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003811 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003812 goto error;
3813 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003814 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003815 if (!inc->ref) {
3816 goto error;
3817 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003819 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 goto error;
3821 }
3822 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003823
Radek Krejcie534c132016-11-23 13:32:31 +01003824 /* process extensions */
3825 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003826 /* some extensions may be already present from the substatements */
3827 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003828 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003829 inc->ext = reallocated;
3830
3831 /* init memory */
3832 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3833
Radek Krejcie534c132016-11-23 13:32:31 +01003834 LY_TREE_FOR_SAFE(exts.child, next, child) {
3835 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003836 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 +01003837 inc->ext_size++;
3838 if (r) {
3839 goto error;
3840 }
3841 }
3842 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003843
Michal Vasko53b7da02018-02-13 15:28:42 +01003844 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003845 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003846
3847error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003848 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003849}
3850
Michal Vasko0d343d12015-08-24 14:57:36 +02003851/* logs directly
3852 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003853 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003854 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003855 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003856 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003858read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3859 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003860{
Radek Krejcie4dce292017-10-30 11:16:47 +01003861 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 const char *value;
3863 struct lyxml_elem *sub, *next;
3864 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003865 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003867 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003868 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003872 GETVAL(ctx, value, xmlnode, "name");
3873 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 goto error;
3875 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003876 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879 /* process local parameters */
3880 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003881 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003882 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003883 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003884 continue;
3885 }
3886 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003887 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003888 continue;
3889 }
3890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003891 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003892 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003893 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003894 goto error;
3895 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003896
Radek Krejci8d6b7422017-02-03 14:42:13 +01003897 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003898 goto error;
3899 }
3900
Radek Krejci1d82ef62015-08-07 14:44:40 +02003901 node->dsc = read_yin_subnode(ctx, sub, "text");
3902 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003903 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 }
3905 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003906 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003907 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003908 goto error;
3909 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003910
Radek Krejci8d6b7422017-02-03 14:42:13 +01003911 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003912 goto error;
3913 }
3914
Radek Krejci1d82ef62015-08-07 14:44:40 +02003915 node->ref = read_yin_subnode(ctx, sub, "text");
3916 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003917 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 }
3919 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003920 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003921 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 goto error;
3923 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003924 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003926 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003927 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003928 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003930 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003931 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003932 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003933 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003935
Radek Krejci8d6b7422017-02-03 14:42:13 +01003936 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003937 goto error;
3938 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003939 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3940 if (opt & OPT_CFG_PARSE) {
3941 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003942 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003943 goto error;
3944 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003945 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003946 if (!strcmp(value, "false")) {
3947 node->flags |= LYS_CONFIG_R;
3948 } else if (!strcmp(value, "true")) {
3949 node->flags |= LYS_CONFIG_W;
3950 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003951 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003952 goto error;
3953 }
3954 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003955
Radek Krejci8d6b7422017-02-03 14:42:13 +01003956 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003957 goto error;
3958 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003961 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 continue;
3963 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003964 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003966
Michal Vaskoe022a562016-09-27 14:24:15 +02003967 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003969 if (parent) {
3970 node->flags |= parent->flags & LYS_CONFIG_MASK;
3971 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003972 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003973 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003974 }
3975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003976
Radek Krejci2cc25322017-09-06 16:32:02 +02003977 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
3978 /* status is not inherited by specification, but it not make sense to have
3979 * current in deprecated or deprecated in obsolete, so we print warning
3980 * and fix the schema by inheriting */
3981 if (!(node->flags & (LYS_STATUS_MASK))) {
3982 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01003983 if (stmt_type == LYEXT_PAR_NODE) {
3984 p = node->parent;
3985 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01003986 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01003987 node->parent = p;
3988 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01003989 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01003990 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003991 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
3992 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02003993 free(str);
3994 node->flags |= parent->flags & LYS_STATUS_MASK;
3995 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
3996 /* invalid combination of statuses */
3997 switch (node->flags & LYS_STATUS_MASK) {
3998 case 0:
3999 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01004000 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004001 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
4002 break;
4003 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01004004 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004005 "obsolete", parent->name);
4006 break;
4007 }
4008 goto error;
4009 }
4010 }
4011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004013
4014error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004016}
4017
Michal Vasko0d343d12015-08-24 14:57:36 +02004018/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004019static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004020read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004021{
Michal Vasko53b7da02018-02-13 15:28:42 +01004022 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004023 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004024 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004025 const char *value;
4026
4027 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004028 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004029
Michal Vasko53b7da02018-02-13 15:28:42 +01004030 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004031 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004032 if (!retval->cond) {
4033 goto error;
4034 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004035
Radek Krejci5323b492017-01-16 15:40:11 +01004036 LY_TREE_FOR_SAFE(yin->child, next, child) {
4037 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004038 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004039 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004040 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4041 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004042 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004043 goto error;
4044 }
4045 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004046 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004047 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004048 goto error;
4049 }
Radek Krejci5323b492017-01-16 15:40:11 +01004050
Radek Krejci8d6b7422017-02-03 14:42:13 +01004051 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004052 goto error;
4053 }
4054
Michal Vasko53b7da02018-02-13 15:28:42 +01004055 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004056 if (!retval->dsc) {
4057 goto error;
4058 }
4059 } else if (!strcmp(child->name, "reference")) {
4060 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004061 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004062 goto error;
4063 }
Radek Krejci5323b492017-01-16 15:40:11 +01004064
Radek Krejci8d6b7422017-02-03 14:42:13 +01004065 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004066 goto error;
4067 }
4068
Michal Vasko53b7da02018-02-13 15:28:42 +01004069 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004070 if (!retval->ref) {
4071 goto error;
4072 }
4073 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004074 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004075 goto error;
4076 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004077 }
4078
4079 return retval;
4080
4081error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004082 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004083 return NULL;
4084}
4085
Michal Vasko0d343d12015-08-24 14:57:36 +02004086/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004087static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004088read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004089 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004090{
Michal Vasko53b7da02018-02-13 15:28:42 +01004091 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004092 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004093 struct lys_node_case *cs;
4094 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004095 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004096 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004097
Radek Krejcie867c852015-08-27 09:52:34 +02004098 /* init */
4099 memset(&root, 0, sizeof root);
4100
Radek Krejci1d82ef62015-08-07 14:44:40 +02004101 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004102 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004103 cs->nodetype = LYS_CASE;
4104 cs->prev = (struct lys_node *)cs;
4105 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004106
Radek Krejci07d0fb92017-01-13 14:11:05 +01004107 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004108 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004109 goto error;
4110 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004111
Michal Vasko3e3228d2017-02-24 14:55:32 +01004112 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004113
Michal Vasko3a0043f2015-08-12 12:11:30 +02004114 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004115 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004116 goto error;
4117 }
4118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004119 /* process choice's specific children */
4120 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004121 if (strcmp(sub->ns->value, LY_NSYIN)) {
4122 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004123 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004124 c_ext++;
4125 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004126 !strcmp(sub->name, "leaf-list") ||
4127 !strcmp(sub->name, "leaf") ||
4128 !strcmp(sub->name, "list") ||
4129 !strcmp(sub->name, "uses") ||
4130 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004131 !strcmp(sub->name, "anyxml") ||
4132 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004133
Michal Vasko53b7da02018-02-13 15:28:42 +01004134 lyxml_unlink_elem(ctx, sub, 2);
4135 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004136 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004137 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004138 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004139 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004140 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004141 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004142 goto error;
4143 }
4144
Radek Krejci5323b492017-01-16 15:40:11 +01004145 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004146 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004147 goto error;
4148 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004149
Michal Vasko53b7da02018-02-13 15:28:42 +01004150 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004152 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004153 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004155 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004156
Radek Krejci3cf9e222015-06-18 11:37:50 +02004157 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004158 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004159 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004160 }
Radek Krejcie534c132016-11-23 13:32:31 +01004161 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004162 /* some extensions may be already present from the substatements */
4163 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004164 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004165 retval->ext = reallocated;
4166
4167 /* init memory */
4168 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004169 }
Radek Krejci21c81652017-01-23 10:42:55 +01004170
Radek Krejcie534c132016-11-23 13:32:31 +01004171 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4172 if (strcmp(sub->ns->value, LY_NSYIN)) {
4173 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004174 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 +01004175 retval->ext_size++;
4176 if (ret) {
4177 goto error;
4178 }
4179 } else {
4180 /* if-feature */
4181 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4182 cs->iffeature_size++;
4183 if (ret) {
4184 goto error;
4185 }
4186 }
4187 }
Radek Krejcib388c152015-06-04 17:03:03 +02004188
Michal Vasko29fc0182015-08-24 15:02:39 +02004189 /* last part - process data nodes */
4190 LY_TREE_FOR_SAFE(root.child, next, sub) {
4191 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004192 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004193 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004194 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004195 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004196 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004197 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004198 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004199 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004200 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004201 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004202 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004203 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004204 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004205 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004206 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004207 }
4208 if (!node) {
4209 goto error;
4210 }
4211
Michal Vasko53b7da02018-02-13 15:28:42 +01004212 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004213 }
4214
Michal Vasko508a50d2016-09-07 14:50:33 +02004215 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004216 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004217 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004218 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004219 goto error;
4220 }
4221 } else {
4222 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4223 goto error;
4224 }
4225 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004226 }
4227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004228 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004229
4230error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004231 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004232 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004233 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004234 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004236 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004237}
4238
Michal Vasko0d343d12015-08-24 14:57:36 +02004239/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004240static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004241read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004242 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004243{
Radek Krejci629cdef2016-06-06 15:06:36 +02004244 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004245 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004246 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004247 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004248 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004249 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004250 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004252 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004253 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004254
Radek Krejci76512572015-08-04 09:47:08 +02004255 choice->nodetype = LYS_CHOICE;
4256 choice->prev = (struct lys_node *)choice;
4257 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004258
Radek Krejci07d0fb92017-01-13 14:11:05 +01004259 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004260 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4261 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4262 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004263 goto error;
4264 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004265
Michal Vasko3e3228d2017-02-24 14:55:32 +01004266 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004267
Michal Vasko3a0043f2015-08-12 12:11:30 +02004268 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004269 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004270 goto error;
4271 }
4272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004273 /* process choice's specific children */
4274 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004275 if (strcmp(sub->ns->value, LY_NSYIN)) {
4276 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004277 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004278 c_ext++;
4279 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004280 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004281 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004282 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 goto error;
4284 }
4285 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004286 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004287 goto error;
4288 }
4289 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004290 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004291 goto error;
4292 }
4293 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004294 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 goto error;
4296 }
4297 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004298 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 goto error;
4300 }
4301 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004302 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004303 goto error;
4304 }
4305 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004306 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004307 goto error;
4308 }
4309 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004310 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004311 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004312 goto error;
4313 }
Radek Krejci21c81652017-01-23 10:42:55 +01004314
Radek Krejci8d6b7422017-02-03 14:42:13 +01004315 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004316 goto error;
4317 }
4318
Radek Krejci629cdef2016-06-06 15:06:36 +02004319 dflt = sub;
4320 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004321 continue;
4322 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004324 } else if (!strcmp(sub->name, "mandatory")) {
4325 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004326 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004327 goto error;
4328 }
4329 /* just checking the flags in leaf is not sufficient, we would allow
4330 * multiple mandatory statements with the "false" value
4331 */
4332 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004333
Michal Vasko53b7da02018-02-13 15:28:42 +01004334 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004335 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004336 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004337 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004338 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004339 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004340 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 goto error;
4342 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004343
Radek Krejci8d6b7422017-02-03 14:42:13 +01004344 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004345 goto error;
4346 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004347 } else if (!strcmp(sub->name, "when")) {
4348 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004349 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004350 goto error;
4351 }
4352
Radek Krejci5323b492017-01-16 15:40:11 +01004353 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004354 if (!choice->when) {
4355 goto error;
4356 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004357 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004358 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004359 c_ftrs++;
4360
Michal Vasko345da0a2015-12-02 10:35:55 +01004361 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004362 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004363 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004364 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004365 goto error;
4366 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004368 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004369 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004371
Radek Krejci1d82ef62015-08-07 14:44:40 +02004372 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004373 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004375
Radek Krejci3cf9e222015-06-18 11:37:50 +02004376 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004377 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004378 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004379 }
Radek Krejcie534c132016-11-23 13:32:31 +01004380 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004381 /* some extensions may be already present from the substatements */
4382 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004383 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004384 retval->ext = reallocated;
4385
4386 /* init memory */
4387 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004388 }
4389
Radek Krejcie534c132016-11-23 13:32:31 +01004390 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4391 if (strcmp(sub->ns->value, LY_NSYIN)) {
4392 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004393 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 +01004394 retval->ext_size++;
4395 if (ret) {
4396 goto error;
4397 }
4398 } else {
4399 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4400 choice->iffeature_size++;
4401 if (ret) {
4402 goto error;
4403 }
4404 }
4405 }
4406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004408 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004409 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4410 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004411 goto error;
4412 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004414 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004415 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004416 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004417 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004418 goto error;
4419 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004420 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004421 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004422
Michal Vasko508a50d2016-09-07 14:50:33 +02004423 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004424 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004425 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004426 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004427 goto error;
4428 }
4429 } else {
4430 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4431 goto error;
4432 }
4433 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004434 }
4435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004437
4438error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004439 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004440 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004442}
4443
Michal Vasko0d343d12015-08-24 14:57:36 +02004444/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004445static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004446read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004447 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004448{
Michal Vasko53b7da02018-02-13 15:28:42 +01004449 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004450 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004451 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 struct lyxml_elem *sub, *next;
4453 const char *value;
4454 int r;
4455 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004456 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004457 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004460 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004461
Radek Krejcibf2abff2016-08-23 15:51:52 +02004462 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004463 anyxml->prev = (struct lys_node *)anyxml;
4464 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004465
Radek Krejci07d0fb92017-01-13 14:11:05 +01004466 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004467 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004468 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 goto error;
4470 }
Radek Krejci863c2852015-06-03 15:47:11 +02004471
Michal Vasko3e3228d2017-02-24 14:55:32 +01004472 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004473
Radek Krejcic189a952016-07-11 15:27:07 +02004474 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004475 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004476 goto error;
4477 }
4478
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004480 if (strcmp(sub->ns->value, LY_NSYIN)) {
4481 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004482 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004483 c_ext++;
4484 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004486 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004487 goto error;
4488 }
4489 /* just checking the flags in leaf is not sufficient, we would allow
4490 * multiple mandatory statements with the "false" value
4491 */
4492 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004493
Michal Vasko53b7da02018-02-13 15:28:42 +01004494 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004496 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004497 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004498 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004499 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004500 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004501 goto error;
4502 }
4503 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004504
Radek Krejci8d6b7422017-02-03 14:42:13 +01004505 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004506 goto error;
4507 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004508 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004509 } else if (!strcmp(sub->name, "when")) {
4510 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004511 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004512 goto error;
4513 }
4514
Radek Krejci5323b492017-01-16 15:40:11 +01004515 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004516 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004517 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004518 goto error;
4519 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004520 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004522 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004524 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004525 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004526 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004529 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 }
4532 }
Radek Krejci863c2852015-06-03 15:47:11 +02004533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 /* middle part - process nodes with cardinality of 0..n */
4535 if (c_must) {
4536 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004537 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004539 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004540 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004541 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004542 }
Radek Krejcie534c132016-11-23 13:32:31 +01004543 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004544 /* some extensions may be already present from the substatements */
4545 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004546 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004547 retval->ext = reallocated;
4548
4549 /* init memory */
4550 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004551 }
Radek Krejci863c2852015-06-03 15:47:11 +02004552
Radek Krejcie534c132016-11-23 13:32:31 +01004553 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4554 if (strcmp(sub->ns->value, LY_NSYIN)) {
4555 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004556 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 +01004557 retval->ext_size++;
4558 if (r) {
4559 goto error;
4560 }
4561 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004562 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004563 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 if (r) {
4565 goto error;
4566 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004567 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004568 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004569 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004570 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004571 goto error;
4572 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 }
Radek Krejci863c2852015-06-03 15:47:11 +02004575
Michal Vasko508a50d2016-09-07 14:50:33 +02004576 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004577 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004578 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004579 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004580 goto error;
4581 }
4582 } else {
4583 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4584 goto error;
4585 }
4586 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004587 }
4588
PavolVican92f23622017-12-12 13:35:56 +01004589 for (r = 0; r < retval->ext_size; ++r) {
4590 /* set flag, which represent LYEXT_OPT_VALID */
4591 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004592 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004593 break;
4594 }
4595 }
4596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004598
4599error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004600 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004602}
4603
Michal Vasko0d343d12015-08-24 14:57:36 +02004604/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004605static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004606read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004607 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004608{
Michal Vasko53b7da02018-02-13 15:28:42 +01004609 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004610 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004611 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 struct lyxml_elem *sub, *next;
4613 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004614 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004615 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004616 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004617
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004619 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004620
Radek Krejci76512572015-08-04 09:47:08 +02004621 leaf->nodetype = LYS_LEAF;
4622 leaf->prev = (struct lys_node *)leaf;
4623 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004624
Radek Krejci07d0fb92017-01-13 14:11:05 +01004625 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004626 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4627 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4628 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 goto error;
4630 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004631
Michal Vasko3e3228d2017-02-24 14:55:32 +01004632 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004633
Radek Krejcic189a952016-07-11 15:27:07 +02004634 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004635 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004636 goto error;
4637 }
4638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004639 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004640 if (strcmp(sub->ns->value, LY_NSYIN)) {
4641 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004642 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004643 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004644 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004645 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004646 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004647 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 goto error;
4649 }
Michal Vasko88c29542015-11-27 14:57:53 +01004650 /* HACK for unres */
4651 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004652 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004653 /* postpone type resolution when if-feature parsing is done since we need
4654 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004655 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 } else if (!strcmp(sub->name, "default")) {
4657 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004658 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 goto error;
4660 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004661 GETVAL(ctx, value, sub, "value");
4662 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004663
Radek Krejci8d6b7422017-02-03 14:42:13 +01004664 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004665 goto error;
4666 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 } else if (!strcmp(sub->name, "units")) {
4668 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004669 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004670 goto error;
4671 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004672 GETVAL(ctx, value, sub, "name");
4673 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004674
Radek Krejci8d6b7422017-02-03 14:42:13 +01004675 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004676 goto error;
4677 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 } else if (!strcmp(sub->name, "mandatory")) {
4679 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004680 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 goto error;
4682 }
4683 /* just checking the flags in leaf is not sufficient, we would allow
4684 * multiple mandatory statements with the "false" value
4685 */
4686 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004687
Michal Vasko53b7da02018-02-13 15:28:42 +01004688 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004690 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004691 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004692 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004693 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004694 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 goto error;
4696 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004697
Radek Krejci8d6b7422017-02-03 14:42:13 +01004698 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004699 goto error;
4700 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004701 } else if (!strcmp(sub->name, "when")) {
4702 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004703 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004704 goto error;
4705 }
4706
Radek Krejci5323b492017-01-16 15:40:11 +01004707 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004708 if (!leaf->when) {
4709 goto error;
4710 }
4711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004712 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004713 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004714 c_must++;
4715 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004716 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004717 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004718 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004722 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004723 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004725
Michal Vasko88c29542015-11-27 14:57:53 +01004726 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004729 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004730 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004731 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 goto error;
4733 }
Michal Vasko478c4652016-07-21 12:55:01 +02004734 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004735 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4736 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004737 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4738 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004739 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 /* middle part - process nodes with cardinality of 0..n */
4742 if (c_must) {
4743 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004744 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004746 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004747 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004748 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004749 }
Radek Krejcie534c132016-11-23 13:32:31 +01004750 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004751 /* some extensions may be already present from the substatements */
4752 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004753 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004754 retval->ext = reallocated;
4755
4756 /* init memory */
4757 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004758 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004759
Radek Krejcie534c132016-11-23 13:32:31 +01004760 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4761 if (strcmp(sub->ns->value, LY_NSYIN)) {
4762 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004763 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 +01004764 retval->ext_size++;
4765 if (r) {
4766 goto error;
4767 }
4768 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004769 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004770 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 if (r) {
4772 goto error;
4773 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004774 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004775 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004776 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004777 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004778 goto error;
4779 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004781 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004782
Radek Krejcicbb473e2016-09-16 14:48:32 +02004783 /* finalize type parsing */
4784 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4785 leaf->type.der = NULL;
4786 goto error;
4787 }
4788
4789 /* check default value (if not defined, there still could be some restrictions
4790 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01004791 if (!(options & LYS_PARSE_OPT_INGRP) && !(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004792 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4793 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004794 goto error;
4795 }
4796
Michal Vasko508a50d2016-09-07 14:50:33 +02004797 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004798 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004799 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004800 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004801 goto error;
4802 }
4803 } else {
4804 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4805 goto error;
4806 }
4807 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004808 }
4809
PavolVican92f23622017-12-12 13:35:56 +01004810 for (r = 0; r < retval->ext_size; ++r) {
4811 /* set flag, which represent LYEXT_OPT_VALID */
4812 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004813 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004814 break;
4815 }
4816 }
4817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004818 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004819
4820error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004821 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004823}
4824
Michal Vasko0d343d12015-08-24 14:57:36 +02004825/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004826static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004827read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004828 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004829{
Michal Vasko53b7da02018-02-13 15:28:42 +01004830 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004831 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004832 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 struct lyxml_elem *sub, *next;
4834 const char *value;
4835 char *endptr;
4836 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004837 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004838 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004839 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004840 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004843 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004844
Radek Krejci76512572015-08-04 09:47:08 +02004845 llist->nodetype = LYS_LEAFLIST;
4846 llist->prev = (struct lys_node *)llist;
4847 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004848
Radek Krejci07d0fb92017-01-13 14:11:05 +01004849 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004850 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4851 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4852 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004853 goto error;
4854 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004855
Michal Vasko3e3228d2017-02-24 14:55:32 +01004856 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004857
Radek Krejcic189a952016-07-11 15:27:07 +02004858 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004859 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004860 goto error;
4861 }
4862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004864 if (strcmp(sub->ns->value, LY_NSYIN)) {
4865 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004866 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004867 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004868 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004869 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004870 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004871 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 goto error;
4873 }
Michal Vasko88c29542015-11-27 14:57:53 +01004874 /* HACK for unres */
4875 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004876 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004877 /* postpone type resolution when if-feature parsing is done since we need
4878 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004879 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004880 } else if (!strcmp(sub->name, "units")) {
4881 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004882 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 goto error;
4884 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004885 GETVAL(ctx, value, sub, "name");
4886 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004887
Radek Krejci8d6b7422017-02-03 14:42:13 +01004888 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004889 goto error;
4890 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 } else if (!strcmp(sub->name, "ordered-by")) {
4892 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004893 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 goto error;
4895 }
4896 /* just checking the flags in llist is not sufficient, we would
4897 * allow multiple ordered-by statements with the "system" value
4898 */
4899 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004900
Radek Krejci1574a8d2015-08-03 14:16:52 +02004901 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4903 * state data
4904 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004905 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 continue;
4907 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004908
Michal Vasko53b7da02018-02-13 15:28:42 +01004909 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004910 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004911 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004913 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004914 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004915 } /* else system is the default value, so we can ignore it */
4916
Radek Krejci8d6b7422017-02-03 14:42:13 +01004917 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004918 goto error;
4919 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004921 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004922 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004923 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004924 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004925 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004926 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004927 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004928 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004929 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004930 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004931 goto error;
4932 }
4933
Michal Vasko53b7da02018-02-13 15:28:42 +01004934 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004935 c_dflt++;
4936 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004938 } else if (!strcmp(sub->name, "min-elements")) {
4939 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004940 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004941 goto error;
4942 }
4943 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004944
Michal Vasko53b7da02018-02-13 15:28:42 +01004945 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946 while (isspace(value[0])) {
4947 value++;
4948 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004950 /* convert it to uint32_t */
4951 errno = 0;
4952 endptr = NULL;
4953 val = strtoul(value, &endptr, 10);
4954 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004955 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 goto error;
4957 }
4958 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004959 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004960 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4961 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004962 goto error;
4963 }
Radek Krejci5323b492017-01-16 15:40:11 +01004964
Radek Krejci8d6b7422017-02-03 14:42:13 +01004965 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004966 goto error;
4967 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004968 } else if (!strcmp(sub->name, "max-elements")) {
4969 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004970 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971 goto error;
4972 }
4973 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004974
Michal Vasko53b7da02018-02-13 15:28:42 +01004975 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 while (isspace(value[0])) {
4977 value++;
4978 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004979
Radek Krejci0d7b2472016-02-12 11:11:03 +01004980 if (!strcmp(value, "unbounded")) {
4981 llist->max = 0;
4982 } else {
4983 /* convert it to uint32_t */
4984 errno = 0;
4985 endptr = NULL;
4986 val = strtoul(value, &endptr, 10);
4987 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004988 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004989 goto error;
4990 }
4991 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004992 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004993 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4994 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004995 goto error;
4996 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 }
Radek Krejci5323b492017-01-16 15:40:11 +01004998
Radek Krejci8d6b7422017-02-03 14:42:13 +01004999 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005000 goto error;
5001 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005002 } else if (!strcmp(sub->name, "when")) {
5003 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005004 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005005 goto error;
5006 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005007
Radek Krejci5323b492017-01-16 15:40:11 +01005008 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005009 if (!llist->when) {
5010 goto error;
5011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005012 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005013 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005014 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005015 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005016
Michal Vasko88c29542015-11-27 14:57:53 +01005017 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005020 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005021 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005022 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 goto error;
5024 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005026 /* middle part - process nodes with cardinality of 0..n */
5027 if (c_must) {
5028 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005029 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005030 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005031 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005032 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005033 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005034 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005035 if (c_dflt) {
5036 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005037 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005038 }
Radek Krejcie534c132016-11-23 13:32:31 +01005039 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005040 /* some extensions may be already present from the substatements */
5041 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005042 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005043 retval->ext = reallocated;
5044
5045 /* init memory */
5046 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005047 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005048
Radek Krejcie534c132016-11-23 13:32:31 +01005049 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5050 if (strcmp(sub->ns->value, LY_NSYIN)) {
5051 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005052 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 +01005053 retval->ext_size++;
5054 if (r) {
5055 goto error;
5056 }
5057 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005058 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005059 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005060 if (r) {
5061 goto error;
5062 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005063 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005064 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005065 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005066 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005067 goto error;
5068 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005069 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005070 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005071
Radek Krejciac1a52c2016-09-15 14:42:40 +02005072 /* check for duplicity in case of configuration data,
5073 * in case of status data duplicities are allowed */
5074 if (llist->flags & LYS_CONFIG_W) {
5075 for (r = 0; r < llist->dflt_size; r++) {
5076 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005077 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5078 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005079 goto error;
5080 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005081 }
5082 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005083 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005084 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005086
Radek Krejcicbb473e2016-09-16 14:48:32 +02005087 /* finalize type parsing */
5088 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5089 llist->type.der = NULL;
5090 goto error;
5091 }
5092
Radek Krejcid5a5c282016-08-15 15:38:08 +02005093 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005094 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5095 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005096 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5097 goto error;
5098 }
5099
5100 /* check default value (if not defined, there still could be some restrictions
5101 * that need to be checked against a default value from a derived type) */
5102 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005103 if (!(options & LYS_PARSE_OPT_INGRP) && !(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005104 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5105 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005106 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005107 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005108 }
5109
Michal Vasko508a50d2016-09-07 14:50:33 +02005110 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005111 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005112 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005113 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005114 goto error;
5115 }
5116 } else {
5117 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5118 goto error;
5119 }
5120 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005121 }
5122
PavolVican92f23622017-12-12 13:35:56 +01005123 for (r = 0; r < retval->ext_size; ++r) {
5124 /* set flag, which represent LYEXT_OPT_VALID */
5125 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005126 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005127 break;
5128 }
5129 }
5130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005132
5133error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005134 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005136}
5137
Michal Vasko0d343d12015-08-24 14:57:36 +02005138/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005139static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005140read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005141 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005142{
Michal Vasko53b7da02018-02-13 15:28:42 +01005143 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005144 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005145 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005146 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005147 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005148 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005149 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005150 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 char *auxs;
5152 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005153 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005155 /* init */
5156 memset(&root, 0, sizeof root);
5157 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005159 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005160 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005161
Radek Krejci76512572015-08-04 09:47:08 +02005162 list->nodetype = LYS_LIST;
5163 list->prev = (struct lys_node *)list;
5164 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005165
Radek Krejci07d0fb92017-01-13 14:11:05 +01005166 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005167 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5168 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5169 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005170 goto error;
5171 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005172
Michal Vasko3e3228d2017-02-24 14:55:32 +01005173 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005174
Radek Krejcic189a952016-07-11 15:27:07 +02005175 /* insert the node into the schema tree */
5176 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5177 goto error;
5178 }
5179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005180 /* process list's specific children */
5181 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005182 if (strcmp(sub->ns->value, LY_NSYIN)) {
5183 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005184 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005185 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005186 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005189 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 !strcmp(sub->name, "leaf-list") ||
5191 !strcmp(sub->name, "leaf") ||
5192 !strcmp(sub->name, "list") ||
5193 !strcmp(sub->name, "choice") ||
5194 !strcmp(sub->name, "uses") ||
5195 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005196 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005197 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005198 !strcmp(sub->name, "action") ||
5199 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005200 lyxml_unlink_elem(ctx, sub, 2);
5201 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005203 /* array counters */
5204 } else if (!strcmp(sub->name, "key")) {
5205 /* check cardinality 0..1 */
5206 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005207 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 goto error;
5209 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005212 GETVAL(ctx, value, sub, "value");
5213 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005214 while ((value = strpbrk(value, " \t\n"))) {
5215 list->keys_size++;
5216 while (isspace(*value)) {
5217 value++;
5218 }
5219 }
5220 list->keys_size++;
5221 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005222 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005223
Radek Krejci8d6b7422017-02-03 14:42:13 +01005224 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005225 goto error;
5226 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005227 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005228 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005229 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005231 lyxml_unlink_elem(ctx, sub, 2);
5232 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005234 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005235 c_tpdf++;
5236 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005237 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005238 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005239 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005240 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005241 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243 /* optional stetments */
5244 } else if (!strcmp(sub->name, "ordered-by")) {
5245 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005246 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 goto error;
5248 }
5249 /* just checking the flags in llist is not sufficient, we would
5250 * allow multiple ordered-by statements with the "system" value
5251 */
5252 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005253
Radek Krejci1574a8d2015-08-03 14:16:52 +02005254 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005255 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5256 * state data
5257 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005258 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 continue;
5260 }
Radek Krejci345ad742015-06-03 11:04:18 +02005261
Michal Vasko53b7da02018-02-13 15:28:42 +01005262 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005264 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005265 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005266 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005267 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005268 } /* else system is the default value, so we can ignore it */
5269
Radek Krejci8d6b7422017-02-03 14:42:13 +01005270 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005271 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005273 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 } else if (!strcmp(sub->name, "min-elements")) {
5275 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005276 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 goto error;
5278 }
5279 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005280
Michal Vasko53b7da02018-02-13 15:28:42 +01005281 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005282 while (isspace(value[0])) {
5283 value++;
5284 }
Radek Krejci345ad742015-06-03 11:04:18 +02005285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 /* convert it to uint32_t */
5287 errno = 0;
5288 auxs = NULL;
5289 val = strtoul(value, &auxs, 10);
5290 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005291 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 goto error;
5293 }
5294 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005295 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005296 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5297 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5298 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005299 goto error;
5300 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005301 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005302 goto error;
5303 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005304 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005305 } else if (!strcmp(sub->name, "max-elements")) {
5306 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005307 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 goto error;
5309 }
5310 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005311
Michal Vasko53b7da02018-02-13 15:28:42 +01005312 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 while (isspace(value[0])) {
5314 value++;
5315 }
Radek Krejci345ad742015-06-03 11:04:18 +02005316
Radek Krejci0d7b2472016-02-12 11:11:03 +01005317 if (!strcmp(value, "unbounded")) {
5318 list->max = 0;;
5319 } else {
5320 /* convert it to uint32_t */
5321 errno = 0;
5322 auxs = NULL;
5323 val = strtoul(value, &auxs, 10);
5324 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005325 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005326 goto error;
5327 }
5328 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005329 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005330 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5331 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005332 goto error;
5333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005335 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005336 goto error;
5337 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005338 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005339 } else if (!strcmp(sub->name, "when")) {
5340 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005341 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005342 goto error;
5343 }
5344
Radek Krejci5323b492017-01-16 15:40:11 +01005345 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005346 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005347 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005348 goto error;
5349 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005350 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005351 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005352 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005353 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005354 }
5355 }
Radek Krejci345ad742015-06-03 11:04:18 +02005356
Michal Vaskoe022a562016-09-27 14:24:15 +02005357 /* check - if list is configuration, key statement is mandatory
5358 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005359 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005360 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005361 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005362 goto error;
5363 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005365 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5366 if (c_tpdf) {
5367 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005368 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005370 if (c_must) {
5371 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005372 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005373 }
5374 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005375 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005376 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005377 }
Radek Krejcie534c132016-11-23 13:32:31 +01005378 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005379 /* some extensions may be already present from the substatements */
5380 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005381 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005382 retval->ext = reallocated;
5383
5384 /* init memory */
5385 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005386 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005387
Radek Krejcie534c132016-11-23 13:32:31 +01005388 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5389 if (strcmp(sub->ns->value, LY_NSYIN)) {
5390 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005391 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 +01005392 retval->ext_size++;
5393 if (r) {
5394 goto error;
5395 }
5396 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005397 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5398 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005399 if (r) {
5400 goto error;
5401 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005402 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005403 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005404 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005405 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005406 goto error;
5407 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005408 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005409 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005410 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005411 if (r) {
5412 goto error;
5413 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005414 }
5415 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005417 /* last part - process data nodes */
5418 LY_TREE_FOR_SAFE(root.child, next, sub) {
5419 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005420 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005421 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005422 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005423 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005424 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005426 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005428 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005429 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005430 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005431 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005432 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005433 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005434 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005435 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005436 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005437 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005438 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005439 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005440 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005441 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005442 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005443 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005444 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005445 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005446 goto error;
5447 }
Radek Krejci73adb602015-07-02 18:07:40 +02005448
Michal Vasko53b7da02018-02-13 15:28:42 +01005449 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005450 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005451
Radek Krejci5c08a992016-11-02 13:30:04 +01005452 if (list->keys_str) {
5453 /* check that we are not in grouping */
5454 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5455 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005456 goto error;
5457 }
5458 } /* 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 +02005459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005460 /* process unique statements */
5461 if (c_uniq) {
5462 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005463 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005464
Radek Krejci461efb92016-02-12 15:52:18 +01005465 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5466 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5467 list->unique_size++;
5468 if (r) {
5469 goto error;
5470 }
5471
Radek Krejci8d6b7422017-02-03 14:42:13 +01005472 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005473 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5474 goto error;
5475 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005476 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005477 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005478 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005479
Michal Vasko508a50d2016-09-07 14:50:33 +02005480 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005481 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005482 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005483 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005484 goto error;
5485 }
5486 } else {
5487 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5488 goto error;
5489 }
5490 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005491 }
5492
PavolVican92f23622017-12-12 13:35:56 +01005493 for (r = 0; r < retval->ext_size; ++r) {
5494 /* set flag, which represent LYEXT_OPT_VALID */
5495 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005496 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005497 break;
5498 }
5499 }
5500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005501 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005502
5503error:
5504
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005505 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005506 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005507 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005508 }
5509 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005510 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005511 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005513 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005514}
5515
Michal Vasko0d343d12015-08-24 14:57:36 +02005516/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005517static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005518read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005519 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005520{
Michal Vasko53b7da02018-02-13 15:28:42 +01005521 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005522 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005523 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005524 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005525 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005526 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005527 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005528 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005529 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005531 /* init */
5532 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005534 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005535 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005536
Radek Krejci76512572015-08-04 09:47:08 +02005537 cont->nodetype = LYS_CONTAINER;
5538 cont->prev = (struct lys_node *)cont;
5539 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005540
Radek Krejci07d0fb92017-01-13 14:11:05 +01005541 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005542 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5543 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5544 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005545 goto error;
5546 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005547
Michal Vasko3e3228d2017-02-24 14:55:32 +01005548 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005549
Radek Krejcic189a952016-07-11 15:27:07 +02005550 /* insert the node into the schema tree */
5551 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5552 goto error;
5553 }
5554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005555 /* process container's specific children */
5556 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005557 if (strcmp(sub->ns->value, LY_NSYIN)) {
5558 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005559 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005560 c_ext++;
5561 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005563 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005564 goto error;
5565 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005566 GETVAL(ctx, value, sub, "value");
5567 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005568
Radek Krejci8d6b7422017-02-03 14:42:13 +01005569 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005570 goto error;
5571 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005572 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005573 } else if (!strcmp(sub->name, "when")) {
5574 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005575 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005576 goto error;
5577 }
5578
Radek Krejci5323b492017-01-16 15:40:11 +01005579 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005580 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005581 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005582 goto error;
5583 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005584 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005586 /* data statements */
5587 } else if (!strcmp(sub->name, "container") ||
5588 !strcmp(sub->name, "leaf-list") ||
5589 !strcmp(sub->name, "leaf") ||
5590 !strcmp(sub->name, "list") ||
5591 !strcmp(sub->name, "choice") ||
5592 !strcmp(sub->name, "uses") ||
5593 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005594 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005595 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005596 !strcmp(sub->name, "action") ||
5597 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005598 lyxml_unlink_elem(ctx, sub, 2);
5599 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005601 /* array counters */
5602 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005603 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005604 c_tpdf++;
5605 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005606 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005607 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005608 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005609 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005610 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005611 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005612 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005613 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 }
5615 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005617 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5618 if (c_tpdf) {
5619 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005620 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005621 }
5622 if (c_must) {
5623 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005624 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005625 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005626 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005627 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005628 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005629 }
Radek Krejcie534c132016-11-23 13:32:31 +01005630 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005631 /* some extensions may be already present from the substatements */
5632 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005633 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005634 retval->ext = reallocated;
5635
5636 /* init memory */
5637 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005638 }
Radek Krejci800af702015-06-02 13:46:01 +02005639
Radek Krejcie534c132016-11-23 13:32:31 +01005640 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5641 if (strcmp(sub->ns->value, LY_NSYIN)) {
5642 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005643 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 +01005644 retval->ext_size++;
5645 if (r) {
5646 goto error;
5647 }
5648 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005649 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5650 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005651 if (r) {
5652 goto error;
5653 }
5654 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005655 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005656 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005657 if (r) {
5658 goto error;
5659 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005660 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005661 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005662 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005663 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005664 goto error;
5665 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005666 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005667 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 /* last part - process data nodes */
5670 LY_TREE_FOR_SAFE(root.child, next, sub) {
5671 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005672 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005673 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005674 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005675 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005676 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005677 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005678 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005679 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005680 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005681 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005682 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005683 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005684 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005685 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005686 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005687 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005688 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005689 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005690 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005691 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005692 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005693 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005694 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005695 goto error;
5696 }
Radek Krejci73adb602015-07-02 18:07:40 +02005697
Michal Vasko53b7da02018-02-13 15:28:42 +01005698 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005699 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005700
Michal Vasko508a50d2016-09-07 14:50:33 +02005701 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005702 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005703 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005704 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005705 goto error;
5706 }
5707 } else {
5708 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5709 goto error;
5710 }
5711 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005712 }
5713
PavolVican92f23622017-12-12 13:35:56 +01005714 for (r = 0; r < retval->ext_size; ++r) {
5715 /* set flag, which represent LYEXT_OPT_VALID */
5716 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005717 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005718 break;
5719 }
5720 }
5721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005722 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005723
5724error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005725 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005726 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005727 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005728 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005730}
5731
Michal Vasko0d343d12015-08-24 14:57:36 +02005732/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005733static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005734read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005735 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005736{
Michal Vasko53b7da02018-02-13 15:28:42 +01005737 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005738 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005739 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005740 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005741 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005742 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005743 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005744 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005746 /* init */
5747 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005750 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005751
Radek Krejci76512572015-08-04 09:47:08 +02005752 grp->nodetype = LYS_GROUPING;
5753 grp->prev = (struct lys_node *)grp;
5754 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005755
Radek Krejci07d0fb92017-01-13 14:11:05 +01005756 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005757 goto error;
5758 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005759
Michal Vasko3e3228d2017-02-24 14:55:32 +01005760 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005761
Radek Krejcic189a952016-07-11 15:27:07 +02005762 /* insert the node into the schema tree */
5763 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5764 goto error;
5765 }
5766
Radek Krejci1d82ef62015-08-07 14:44:40 +02005767 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005768 if (strcmp(sub->ns->value, LY_NSYIN)) {
5769 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005770 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005771 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005773 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005774 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005775 !strcmp(sub->name, "leaf-list") ||
5776 !strcmp(sub->name, "leaf") ||
5777 !strcmp(sub->name, "list") ||
5778 !strcmp(sub->name, "choice") ||
5779 !strcmp(sub->name, "uses") ||
5780 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005781 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005782 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005783 !strcmp(sub->name, "action") ||
5784 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005785 lyxml_unlink_elem(ctx, sub, 2);
5786 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005788 /* array counters */
5789 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005790 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005791 c_tpdf++;
5792 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005793 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005794 goto error;
5795 }
5796 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005798 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5799 if (c_tpdf) {
5800 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005801 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005802 }
Radek Krejcie534c132016-11-23 13:32:31 +01005803 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005804 /* some extensions may be already present from the substatements */
5805 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005806 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005807 retval->ext = reallocated;
5808
5809 /* init memory */
5810 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005811 }
Radek Krejcie534c132016-11-23 13:32:31 +01005812 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5813 if (strcmp(sub->ns->value, LY_NSYIN)) {
5814 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005815 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 +01005816 retval->ext_size++;
5817 if (r) {
5818 goto error;
5819 }
5820 } else {
5821 /* typedef */
5822 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5823 grp->tpdf_size++;
5824 if (r) {
5825 goto error;
5826 }
5827 }
5828 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005830 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005831 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005832 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005833 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005834 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005835 LY_TREE_FOR_SAFE(root.child, next, sub) {
5836 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005837 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005838 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005839 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005840 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005841 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005842 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005843 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005844 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005845 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005846 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005847 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005848 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005849 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005850 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005851 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005852 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005853 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005854 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005855 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005856 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005857 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005858 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005859 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005860 goto error;
5861 }
Radek Krejci73adb602015-07-02 18:07:40 +02005862
Michal Vasko53b7da02018-02-13 15:28:42 +01005863 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005866 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005867
5868error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005869 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005870 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005871 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005872 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005873 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005874}
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_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005879 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005880{
Michal Vasko53b7da02018-02-13 15:28:42 +01005881 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005882 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005883 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005884 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005885 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005886 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005887 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005888
Radek Krejcie0674f82015-06-15 13:58:51 +02005889 /* init */
5890 memset(&root, 0, sizeof root);
5891
Michal Vasko38d01f72015-06-15 09:41:06 +02005892 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005893 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005894 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005895
5896 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005897 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005898 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005899 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005900 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005901 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005902 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005903 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005904 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005905 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005906 }
5907
Radek Krejci76512572015-08-04 09:47:08 +02005908 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005909 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005910
Michal Vasko3e3228d2017-02-24 14:55:32 +01005911 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005912
Radek Krejcic189a952016-07-11 15:27:07 +02005913 /* insert the node into the schema tree */
5914 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5915 goto error;
5916 }
5917
Michal Vasko38d01f72015-06-15 09:41:06 +02005918 /* data statements */
5919 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005920 if (!sub->ns) {
5921 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005922 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005923 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005924 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005925 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005926 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005927 c_ext++;
5928 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005929 !strcmp(sub->name, "leaf-list") ||
5930 !strcmp(sub->name, "leaf") ||
5931 !strcmp(sub->name, "list") ||
5932 !strcmp(sub->name, "choice") ||
5933 !strcmp(sub->name, "uses") ||
5934 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005935 !strcmp(sub->name, "anyxml") ||
5936 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005937 lyxml_unlink_elem(ctx, sub, 2);
5938 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005940 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005941 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005942 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02005943 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005944 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005945
Radek Krejci1a31efe2016-07-29 11:04:16 +02005946 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005947 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02005948 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02005949 c_must++;
5950
Michal Vasko38d01f72015-06-15 09:41:06 +02005951 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005952 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005953 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005954 }
5955 }
5956
5957 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5958 if (c_tpdf) {
5959 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005960 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005961 }
Radek Krejci19332802016-07-29 10:39:46 +02005962 if (c_must) {
5963 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005964 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02005965 }
Radek Krejcie534c132016-11-23 13:32:31 +01005966 if (c_ext) {
5967 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005968 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01005969 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005970
Radek Krejcie534c132016-11-23 13:32:31 +01005971 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5972 if (strcmp(sub->ns->value, LY_NSYIN)) {
5973 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005974 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 +01005975 retval->ext_size++;
5976 if (r) {
5977 goto error;
5978 }
5979 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005980 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005981 inout->must_size++;
5982 if (r) {
5983 goto error;
5984 }
5985 } else { /* typedef */
5986 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5987 inout->tpdf_size++;
5988 if (r) {
5989 goto error;
5990 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005991 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005992 }
5993
5994 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005995 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02005996 LY_TREE_FOR_SAFE(root.child, next, sub) {
5997 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005998 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005999 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006000 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006001 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006002 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006003 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006004 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006005 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006006 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006007 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006008 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006009 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006010 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006011 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006012 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006013 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006014 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006015 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006016 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006017 goto error;
6018 }
Radek Krejci73adb602015-07-02 18:07:40 +02006019
Michal Vasko53b7da02018-02-13 15:28:42 +01006020 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006021 }
6022
Michal Vasko508a50d2016-09-07 14:50:33 +02006023 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006024 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006025 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006026 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006027 goto error;
6028 }
6029 } else {
6030 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6031 goto error;
6032 }
6033 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006034 }
6035
Michal Vasko38d01f72015-06-15 09:41:06 +02006036 return retval;
6037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006038error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006039 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006040 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006041 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006042 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006043 return NULL;
6044}
6045
Michal Vasko0d343d12015-08-24 14:57:36 +02006046/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006047static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006048read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006049 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006050{
Michal Vasko53b7da02018-02-13 15:28:42 +01006051 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006052 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006053 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006054 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006055 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006056 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006057 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006058 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006059
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006060 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006061 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006062 return NULL;
6063 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006064
Michal Vaskoc6551b32015-06-16 10:51:43 +02006065 memset(&root, 0, sizeof root);
6066
Michal Vasko0ea41032015-06-16 08:53:55 +02006067 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006068 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006069
Radek Krejci76512572015-08-04 09:47:08 +02006070 notif->nodetype = LYS_NOTIF;
6071 notif->prev = (struct lys_node *)notif;
6072 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006073
Radek Krejci07d0fb92017-01-13 14:11:05 +01006074 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006075 goto error;
6076 }
6077
Michal Vasko3e3228d2017-02-24 14:55:32 +01006078 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006079
Radek Krejcic189a952016-07-11 15:27:07 +02006080 /* insert the node into the schema tree */
6081 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6082 goto error;
6083 }
6084
Michal Vasko0ea41032015-06-16 08:53:55 +02006085 /* process rpc's specific children */
6086 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006087 if (strcmp(sub->ns->value, LY_NSYIN)) {
6088 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006089 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006090 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006091 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006092
Michal Vasko0ea41032015-06-16 08:53:55 +02006093 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006094 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006095 !strcmp(sub->name, "leaf-list") ||
6096 !strcmp(sub->name, "leaf") ||
6097 !strcmp(sub->name, "list") ||
6098 !strcmp(sub->name, "choice") ||
6099 !strcmp(sub->name, "uses") ||
6100 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006101 !strcmp(sub->name, "anyxml") ||
6102 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006103 lyxml_unlink_elem(ctx, sub, 2);
6104 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006106 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006107 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006108 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006109 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006110 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006111 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006112 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006113 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006114 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006115 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006116 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006117 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006118 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006119 }
6120 }
6121
6122 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6123 if (c_tpdf) {
6124 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006125 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006126 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006127 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006128 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006129 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006130 }
Radek Krejci19332802016-07-29 10:39:46 +02006131 if (c_must) {
6132 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006133 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006134 }
Radek Krejcie534c132016-11-23 13:32:31 +01006135 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006136 /* some extensions may be already present from the substatements */
6137 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006138 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006139 retval->ext = reallocated;
6140
6141 /* init memory */
6142 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006143 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006144
Radek Krejcie534c132016-11-23 13:32:31 +01006145 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6146 if (strcmp(sub->ns->value, LY_NSYIN)) {
6147 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006148 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 +01006149 retval->ext_size++;
6150 if (r) {
6151 goto error;
6152 }
6153 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006154 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6155 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006156 if (r) {
6157 goto error;
6158 }
Radek Krejci96299152016-06-22 10:17:50 +02006159 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006160 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006161 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006162 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006163 goto error;
6164 }
Radek Krejci19332802016-07-29 10:39:46 +02006165 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006166 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006167 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006168 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006169 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006170 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006171 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006172 }
6173
6174 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006175 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006176 LY_TREE_FOR_SAFE(root.child, next, sub) {
6177 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006178 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006179 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006180 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006181 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006182 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006183 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006184 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006185 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006186 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006187 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006188 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006189 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006190 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006191 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006192 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006193 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006194 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006195 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006196 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006197 goto error;
6198 }
Radek Krejci73adb602015-07-02 18:07:40 +02006199
Michal Vasko53b7da02018-02-13 15:28:42 +01006200 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006201 }
6202
Michal Vasko508a50d2016-09-07 14:50:33 +02006203 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006204 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006205 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006206 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006207 goto error;
6208 }
6209 } else {
6210 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6211 goto error;
6212 }
6213 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006214 }
6215
Michal Vasko0ea41032015-06-16 08:53:55 +02006216 return retval;
6217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006218error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006219 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006220 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006221 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006222 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006223 return NULL;
6224}
6225
Michal Vasko0d343d12015-08-24 14:57:36 +02006226/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006227static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006228read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006229 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006230{
Michal Vasko53b7da02018-02-13 15:28:42 +01006231 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006232 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006233 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006234 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006235 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006236 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006237 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006238 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006239
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006240 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006241 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006242 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006243 return NULL;
6244 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006245 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006246 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006247 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006248 LOGVAL(ctx, LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006249 return NULL;
6250 }
6251 }
6252 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006253
Radek Krejcie0674f82015-06-15 13:58:51 +02006254 /* init */
6255 memset(&root, 0, sizeof root);
6256
Michal Vasko38d01f72015-06-15 09:41:06 +02006257 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006258 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006259
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006260 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006261 rpc->prev = (struct lys_node *)rpc;
6262 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006263
Radek Krejci07d0fb92017-01-13 14:11:05 +01006264 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006265 goto error;
6266 }
6267
Michal Vasko3e3228d2017-02-24 14:55:32 +01006268 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006269
Radek Krejcic189a952016-07-11 15:27:07 +02006270 /* insert the node into the schema tree */
6271 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6272 goto error;
6273 }
6274
Michal Vasko38d01f72015-06-15 09:41:06 +02006275 /* process rpc's specific children */
6276 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006277 if (strcmp(sub->ns->value, LY_NSYIN)) {
6278 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006279 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006280 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006281 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006282 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006283 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006284 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006285 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006286 goto error;
6287 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006288 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006289 lyxml_unlink_elem(ctx, sub, 2);
6290 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006291 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006292 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006293 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006294 goto error;
6295 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006296 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006297 lyxml_unlink_elem(ctx, sub, 2);
6298 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006300 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006301 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006302 lyxml_unlink_elem(ctx, sub, 2);
6303 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006305 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006306 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006307 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006308 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006309 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006310 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006311 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006312 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006313 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006314 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006315 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006316 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006317 }
6318 }
6319
6320 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6321 if (c_tpdf) {
6322 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006323 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006324 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006325 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006326 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006327 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006328 }
Radek Krejcie534c132016-11-23 13:32:31 +01006329 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006330 /* some extensions may be already present from the substatements */
6331 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006332 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006333 retval->ext = reallocated;
6334
6335 /* init memory */
6336 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006337 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006338
Radek Krejcie534c132016-11-23 13:32:31 +01006339 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6340 if (strcmp(sub->ns->value, LY_NSYIN)) {
6341 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006342 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 +01006343 retval->ext_size++;
6344 if (r) {
6345 goto error;
6346 }
6347 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006348 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6349 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006350 if (r) {
6351 goto error;
6352 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006353 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006354 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006355 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006356 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006357 goto error;
6358 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006359 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006360 }
6361
6362 /* last part - process data nodes */
6363 LY_TREE_FOR_SAFE(root.child, next, sub) {
6364 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006365 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006366 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006367 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006368 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006369 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006370 goto error;
6371 }
Radek Krejci73adb602015-07-02 18:07:40 +02006372
Michal Vasko53b7da02018-02-13 15:28:42 +01006373 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006374 }
6375
Michal Vasko38d01f72015-06-15 09:41:06 +02006376 return retval;
6377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006378error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006379 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006380 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006381 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006382 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006383 return NULL;
6384}
6385
Michal Vasko0d343d12015-08-24 14:57:36 +02006386/* logs directly
6387 *
Radek Krejci74705112015-06-05 10:25:44 +02006388 * resolve - referenced grouping should be bounded to the namespace (resolved)
6389 * only when uses does not appear in grouping. In a case of grouping's uses,
6390 * we just get information but we do not apply augment or refine to it.
6391 */
Radek Krejci76512572015-08-04 09:47:08 +02006392static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006393read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6394 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006395{
Michal Vasko53b7da02018-02-13 15:28:42 +01006396 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006397 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006398 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006399 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006400 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006401 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006402 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006403 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006405 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006406 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006407
Radek Krejci76512572015-08-04 09:47:08 +02006408 uses->nodetype = LYS_USES;
6409 uses->prev = (struct lys_node *)uses;
6410 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006411
Michal Vasko53b7da02018-02-13 15:28:42 +01006412 GETVAL(ctx, value, yin, "name");
6413 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006414
Radek Krejci07d0fb92017-01-13 14:11:05 +01006415 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006416 goto error;
6417 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006418
Michal Vasko3e3228d2017-02-24 14:55:32 +01006419 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006420
Radek Krejcic189a952016-07-11 15:27:07 +02006421 /* insert the node into the schema tree */
6422 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6423 goto error;
6424 }
6425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006426 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006427 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006428 if (strcmp(sub->ns->value, LY_NSYIN)) {
6429 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006430 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006431 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006432 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006433 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006434 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006435 c_ref++;
6436 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006437 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006438 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006439 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006440 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006441 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006442 } else if (!strcmp(sub->name, "when")) {
6443 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006444 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006445 goto error;
6446 }
6447
Radek Krejci5323b492017-01-16 15:40:11 +01006448 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006449 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006450 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006451 goto error;
6452 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006453 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006454 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006455 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006456 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006457 }
6458 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006460 /* process properties with cardinality 0..n */
6461 if (c_ref) {
6462 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006463 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006464 }
6465 if (c_aug) {
6466 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006467 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006468 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006469 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006470 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006471 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006472 }
Radek Krejcie534c132016-11-23 13:32:31 +01006473 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006474 /* some extensions may be already present from the substatements */
6475 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006476 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006477 retval->ext = reallocated;
6478
6479 /* init memory */
6480 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006481 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006482
Radek Krejcie534c132016-11-23 13:32:31 +01006483 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6484 if (strcmp(sub->ns->value, LY_NSYIN)) {
6485 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006486 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 +01006487 retval->ext_size++;
6488 if (r) {
6489 goto error;
6490 }
6491 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006492 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006493 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006494 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006495 goto error;
6496 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006497 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006498 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006499 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006500 if (r) {
6501 goto error;
6502 }
6503 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006504 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006505 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006506 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006507 goto error;
6508 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006509 }
6510 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006511
Radek Krejci48464ed2016-03-17 15:44:09 +01006512 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006513 goto error;
6514 }
Radek Krejci74705112015-06-05 10:25:44 +02006515
Michal Vasko508a50d2016-09-07 14:50:33 +02006516 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006517 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006518 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006519 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006520 goto error;
6521 }
6522 } else {
6523 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6524 goto error;
6525 }
6526 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006527 }
6528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006529 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006530
6531error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006532 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006533 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006534}
6535
Michal Vasko0d343d12015-08-24 14:57:36 +02006536/* logs directly
6537 *
6538 * common code for yin_read_module() and yin_read_submodule()
6539 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006540static int
Radek Krejcic071c542016-01-27 14:57:51 +01006541read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6542 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006543{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006544 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006545 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006546 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006547 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006548 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006549 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006550 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006551 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6552 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6553 int substmt_group;
6554 /* just remember last substatement for logging */
6555 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006556 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006557 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;
6558 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006559 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006560
Radek Krejcic071c542016-01-27 14:57:51 +01006561 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006562 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006564 /* init */
6565 memset(&root, 0, sizeof root);
6566 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006567 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006568 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006569 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006571 /*
6572 * in the first run, we process elements with cardinality of 1 or 0..1 and
6573 * count elements with cardinality 0..n. Data elements (choices, containers,
6574 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6575 * need have all top-level and groupings already prepared at that time. In
6576 * the middle loop, we process other elements with carinality of 0..n since
6577 * we need to allocate arrays to store them.
6578 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006579 substmt_group = 0;
6580 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006581 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006582 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006583 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006584 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006585 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006586 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006587 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006588 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006589 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006590 lyxml_unlink_elem(ctx, child, 2);
6591 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006592 c_extinst++;
6593 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006594 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006595 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6596 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006597 child->name, substmt_prev);
6598 goto error;
6599 }
6600
PavolVican9e81c6a2017-02-09 13:09:07 +01006601 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006602 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006603 goto error;
6604 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006605 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006606 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006607
Radek Krejci8d6b7422017-02-03 14:42:13 +01006608 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006609 goto error;
6610 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006611 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006612
6613 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006614 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006615 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006616 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6617 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006618 child->name, substmt_prev);
6619 goto error;
6620 }
6621
PavolVican9e81c6a2017-02-09 13:09:07 +01006622 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006623 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006624 goto error;
6625 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006626 GETVAL(ctx, value, child, "value");
6627 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006628 goto error;
6629 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006630 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006631
Radek Krejci8d6b7422017-02-03 14:42:13 +01006632 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006633 goto error;
6634 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006635 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006636
6637 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006638 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006639 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006640 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6641 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006642 child->name, substmt_prev);
6643 goto error;
6644 }
6645
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006646 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006647 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006648 goto error;
6649 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006650 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006651 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006652 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006653 goto error;
6654 }
Radek Krejcif3886932015-06-04 17:36:06 +02006655
Radek Krejci8d6b7422017-02-03 14:42:13 +01006656 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006657 goto error;
6658 }
6659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006660 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006661 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006662 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006663 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006664 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006665 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006666 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006667 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006668 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006669 goto error;
6670 }
6671 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006672 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006673 /* check here differs from a generic prefix check, since this prefix
6674 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006675 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006676 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006677 goto error;
6678 }
Radek Krejcic071c542016-01-27 14:57:51 +01006679 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006680
Radek Krejci8d6b7422017-02-03 14:42:13 +01006681 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006682 goto error;
6683 }
6684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006685 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006686 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006687
Michal Vasko5de8a022017-02-08 10:57:26 +01006688 substmt_prev = "belongs-to";
6689
Radek Krejcieb00f512015-07-01 16:44:58 +02006690 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006691 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006692 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006693 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6694 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006695 child->name, substmt_prev);
6696 goto error;
6697 }
6698 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006699 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006700 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006701 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006702
6703 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006704 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006705 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006706 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6707 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006708 child->name, substmt_prev);
6709 goto error;
6710 }
6711 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006712 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006713 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006714 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006715
PavolVican9e81c6a2017-02-09 13:09:07 +01006716 lyxml_unlink_elem(ctx, child, 2);
6717 lyxml_add_child(ctx, &revs, child);
6718
Michal Vasko5de8a022017-02-08 10:57:26 +01006719 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006720 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006721 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006722 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006723 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006724 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006725
6726 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006727 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006728 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006729 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006730 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006731 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006732
6733 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006734 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006735 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006736 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6737 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006738 child->name, substmt_prev);
6739 goto error;
6740 }
6741 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006742 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006743 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006744 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006745
6746 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006747 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006748 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006749 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006750 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006751 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006752 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006753 lyxml_unlink_elem(ctx, child, 2);
6754 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006755
Michal Vasko5de8a022017-02-08 10:57:26 +01006756 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006757 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006758 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006759 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006760 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006761 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006762
Michal Vasko5de8a022017-02-08 10:57:26 +01006763 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006765 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006766 } else if (!strcmp(child->name, "container") ||
6767 !strcmp(child->name, "leaf-list") ||
6768 !strcmp(child->name, "leaf") ||
6769 !strcmp(child->name, "list") ||
6770 !strcmp(child->name, "choice") ||
6771 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006772 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006773 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006774 !strcmp(child->name, "rpc") ||
6775 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006776 substmt_group = 4;
6777
Radek Krejcic071c542016-01-27 14:57:51 +01006778 lyxml_unlink_elem(ctx, child, 2);
6779 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006780
Michal Vasko5de8a022017-02-08 10:57:26 +01006781 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006782 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006783 substmt_group = 4;
6784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006785 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006786 lyxml_unlink_elem(ctx, child, 2);
6787 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006788
Michal Vasko5de8a022017-02-08 10:57:26 +01006789 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006790 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006791 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006792 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006793 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6794 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006795 child->name, substmt_prev);
6796 goto error;
6797 }
6798 substmt_group = 2;
6799
Radek Krejcic071c542016-01-27 14:57:51 +01006800 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006801 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006802 goto error;
6803 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006804 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006805 goto error;
6806 }
Radek Krejcic071c542016-01-27 14:57:51 +01006807 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006808 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006809 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006810 goto error;
6811 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006812
6813 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006814 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006815 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006816 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6817 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006818 child->name, substmt_prev);
6819 goto error;
6820 }
6821 substmt_group = 2;
6822
Radek Krejcic071c542016-01-27 14:57:51 +01006823 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006824 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006825 goto error;
6826 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006827 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006828 goto error;
6829 }
Radek Krejcic071c542016-01-27 14:57:51 +01006830 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006831 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006832 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006833 goto error;
6834 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006835
6836 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006837 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006838 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006839 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6840 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006841 child->name, substmt_prev);
6842 goto error;
6843 }
6844 substmt_group = 2;
6845
Radek Krejcic071c542016-01-27 14:57:51 +01006846 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006847 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006848 goto error;
6849 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006850 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006851 goto error;
6852 }
Radek Krejcic071c542016-01-27 14:57:51 +01006853 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006854 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006855 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006856 goto error;
6857 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006858
6859 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006860 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006861 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006862 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6863 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006864 child->name, substmt_prev);
6865 goto error;
6866 }
6867 substmt_group = 2;
6868
Radek Krejcic071c542016-01-27 14:57:51 +01006869 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006870 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006871 goto error;
6872 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006873 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006874 goto error;
6875 }
Radek Krejcic071c542016-01-27 14:57:51 +01006876 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006877 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006878 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006879 goto error;
6880 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006881
6882 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006883 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006884 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006885 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6886 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006887 child->name, substmt_prev);
6888 goto error;
6889 }
6890
Radek Krejcic071c542016-01-27 14:57:51 +01006891 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006892 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006893 goto error;
6894 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006895 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006896 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006897 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006898 goto error;
6899 }
Radek Krejcic071c542016-01-27 14:57:51 +01006900 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006901 if (!strcmp(value, "1")) {
6902 if (submodule) {
6903 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006904 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006905 goto error;
6906 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006907 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006908 } else {
6909 module->version = 1;
6910 }
6911 } else {
6912 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006913 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006914 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006915 goto error;
6916 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006917 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006918 } else {
6919 module->version = 2;
6920 }
6921 }
6922
Radek Krejci8d6b7422017-02-03 14:42:13 +01006923 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006924 goto error;
6925 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006926 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006927
Michal Vasko5de8a022017-02-08 10:57:26 +01006928 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006929 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006930 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006931 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006932 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006933 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006934
Michal Vasko5de8a022017-02-08 10:57:26 +01006935 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006936 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006937 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006938 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006939 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006940 c_dev++;
6941
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006942 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006943 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006944 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006945 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006946 }
6947 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006948
Radek Krejcic071c542016-01-27 14:57:51 +01006949 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006950 if (submodule) {
6951 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006952 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006953 goto error;
6954 }
6955 if (!version_flag) {
6956 /* check version compatibility with the main module */
6957 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006958 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006959 goto error;
6960 }
6961 }
6962 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006963 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006964 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006965 goto error;
6966 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006967 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006968 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006969 goto error;
6970 }
6971 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006973 /* allocate arrays for elements with cardinality of 0..n */
6974 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006975 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01006976 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006977 }
6978 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006979 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01006980 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006981 }
6982 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006983 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006984 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006985 }
6986 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006987 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01006988 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006989 }
6990 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006991 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006992 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006993 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006994 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006995 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006996 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006997 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006998 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006999 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007000 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007001 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007002 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007003 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007004 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007005 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007006 if (c_ext) {
7007 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007008 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007009 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007010
PavolVican9e81c6a2017-02-09 13:09:07 +01007011 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7012 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007013 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7014 trg->rev_size++;
7015 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007016 goto error;
7017 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007018
Radek Krejci7417a082017-02-16 11:07:59 +01007019 /* check uniqueness of the revision date - not required by RFC */
7020 for (i = 0; i < (trg->rev_size - 1); i++) {
7021 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007022 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007023 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007024 }
7025 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007026
7027 lyxml_free(ctx, child);
7028 }
7029
7030 /* check the module with respect to the context now */
7031 if (!submodule) {
7032 switch (lyp_ctx_check_module(module)) {
7033 case -1:
7034 goto error;
7035 case 0:
7036 break;
7037 case 1:
7038 /* it's already there */
7039 ret = 1;
7040 goto error;
7041 }
7042 }
7043
PavolVican92f23622017-12-12 13:35:56 +01007044 /* check first definition of extensions */
7045 if (c_ext) {
7046 LY_TREE_FOR_SAFE(yin->child, next, child) {
7047 if (!strcmp(child->name, "extension")) {
7048 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7049 trg->extensions_size++;
7050 if (r) {
7051 goto error;
7052 }
7053
7054 }
7055 }
7056 }
7057
PavolVican9e81c6a2017-02-09 13:09:07 +01007058 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007059 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007060 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007061 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007062 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007063 if (r) {
7064 goto error;
7065 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007066
Radek Krejci1d82ef62015-08-07 14:44:40 +02007067 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007068 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7069 trg->inc_size++;
7070 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007071 goto error;
7072 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007073
Radek Krejci1d82ef62015-08-07 14:44:40 +02007074 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007075 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7076 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007077 if (r) {
7078 goto error;
7079 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007080
Radek Krejci1d82ef62015-08-07 14:44:40 +02007081 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007082 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7083 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007084 if (r) {
7085 goto error;
7086 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007087
Radek Krejci1d82ef62015-08-07 14:44:40 +02007088 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007089 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7090 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007091 if (r) {
7092 goto error;
7093 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007094
Radek Krejci1d82ef62015-08-07 14:44:40 +02007095 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007096 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7097 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007098 if (r) {
7099 goto error;
7100 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007101 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007102 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007103
Radek Krejcie534c132016-11-23 13:32:31 +01007104 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007105 if (c_extinst) {
7106 /* some extensions may be already present from the substatements */
7107 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007108 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007109 trg->ext = reallocated;
7110
7111 /* init memory */
7112 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7113
7114 LY_TREE_FOR_SAFE(exts.child, next, child) {
7115 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7116 trg->ext_size++;
7117 if (r) {
7118 goto error;
7119 }
7120 }
Radek Krejcie534c132016-11-23 13:32:31 +01007121 }
7122
Radek Krejcif5be10f2015-06-16 13:29:36 +02007123 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007124 * refer to them. Submodule's data nodes are stored in the
7125 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007126 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007127 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007128 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007129 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007130 goto error;
7131 }
Radek Krejci74705112015-06-05 10:25:44 +02007132
Michal Vasko345da0a2015-12-02 10:35:55 +01007133 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007134 }
Radek Krejci74705112015-06-05 10:25:44 +02007135
Radek Krejcif5be10f2015-06-16 13:29:36 +02007136 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007137 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007138
Radek Krejci1d82ef62015-08-07 14:44:40 +02007139 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007140 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007141 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007142 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007143 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007144 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007145 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007146 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007147 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007148 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007149 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007150 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007151 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007152 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007153 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007154 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007155 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007156 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007157 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007158 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007159 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007160 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007161 goto error;
7162 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007163
Michal Vasko345da0a2015-12-02 10:35:55 +01007164 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007165 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007166
Michal Vasko2f7925f2015-10-21 15:06:56 +02007167 /* ... and finally augments (last, so we can augment our data, for instance) */
7168 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007169 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007170 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007171
Michal Vasko2f7925f2015-10-21 15:06:56 +02007172 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007173 goto error;
7174 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007175 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007176 }
7177
PavolVican9e81c6a2017-02-09 13:09:07 +01007178 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007179
7180error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007181 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007182 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007183 }
7184 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007185 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007186 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007187 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007188 lyxml_free(ctx, augs.child);
7189 }
7190 while (revs.child) {
7191 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007192 }
Radek Krejcie534c132016-11-23 13:32:31 +01007193 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007194 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007195 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007196
PavolVican9e81c6a2017-02-09 13:09:07 +01007197 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007198}
7199
Michal Vasko0d343d12015-08-24 14:57:36 +02007200/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007201struct lys_submodule *
7202yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007203{
Michal Vasko53b7da02018-02-13 15:28:42 +01007204 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007205 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007206 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007207 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007208
Michal Vasko53b7da02018-02-13 15:28:42 +01007209 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007210 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007211 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007212 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007214 /* check root element */
7215 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007216 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007217 goto error;
7218 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007219
Michal Vasko53b7da02018-02-13 15:28:42 +01007220 GETVAL(ctx, value, yin, "name");
7221 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007222 goto error;
7223 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007224
Michal Vasko5a721fd2016-02-16 12:16:48 +01007225 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007226 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007227
Michal Vasko53b7da02018-02-13 15:28:42 +01007228 submodule->ctx = ctx;
7229 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007230 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007231 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007232 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007233
Radek Krejci9e757e02017-03-08 17:18:09 +01007234 /* add into the list of processed modules */
7235 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7236 goto error;
7237 }
7238
Michal Vasko5a721fd2016-02-16 12:16:48 +01007239 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007240 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007241 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007242 goto error;
7243 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007244
Radek Krejci33fc4772017-01-26 16:00:35 +01007245 lyp_sort_revisions((struct lys_module *)submodule);
7246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007247 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007248 lyxml_free(ctx, yin);
7249 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007250
Michal Vasko5a721fd2016-02-16 12:16:48 +01007251 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007252 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007253
7254error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007255 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007256 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007257 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007258 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007259 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007260 }
7261
Michal Vasko53b7da02018-02-13 15:28:42 +01007262 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007263
Michal Vaskoa9728122018-01-16 14:00:13 +01007264 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007265 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007266 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7267 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007268 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007269 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007270}
7271
Michal Vasko0d343d12015-08-24 14:57:36 +02007272/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007273struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007274yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007275{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007276 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007277 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007278 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007279 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007280
Radek Krejcic071c542016-01-27 14:57:51 +01007281 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007282 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007284 /* check root element */
7285 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007286 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007287 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007288 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007289 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007290 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007291 goto error;
7292 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007293
Michal Vasko53b7da02018-02-13 15:28:42 +01007294 GETVAL(ctx, value, yin, "name");
7295 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007296 goto error;
7297 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007299 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007300 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007302 module->ctx = ctx;
7303 module->name = lydict_insert(ctx, value, strlen(value));
7304 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007305 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007306
Radek Krejci9e757e02017-03-08 17:18:09 +01007307 /* add into the list of processed modules */
7308 if (lyp_check_circmod_add(module)) {
7309 goto error;
7310 }
7311
Michal Vasko9f258e42016-02-11 11:36:27 +01007312 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007313 ret = read_sub_module(module, NULL, yin, unres);
7314 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007315 goto error;
7316 }
7317
PavolVican9e81c6a2017-02-09 13:09:07 +01007318 if (ret == 1) {
7319 assert(!unres->count);
7320 } else {
7321 /* resolve rest of unres items */
7322 if (unres->count && resolve_unres_schema(module, unres)) {
7323 goto error;
7324 }
7325
7326 /* check correctness of includes */
7327 if (lyp_check_include_missing(module)) {
7328 goto error;
7329 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007330 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007331
Radek Krejci95f22ae2017-01-20 14:25:53 +01007332 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007333
7334 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7335 goto error;
7336 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007337
Radek Krejciff4874d2016-03-07 12:30:50 +01007338 if (revision) {
7339 /* check revision of the parsed model */
7340 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007341 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7342 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007343 goto error;
7344 }
7345 }
7346
PavolVican9e81c6a2017-02-09 13:09:07 +01007347 /* add into context if not already there */
7348 if (!ret) {
7349 if (module->deviation_size && !module->implemented) {
7350 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
7351 /* deviations always causes target to be made implemented,
7352 * but augents and leafrefs not, so we have to apply them now */
7353 if (lys_set_implemented(module)) {
7354 goto error;
7355 }
7356 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007357
PavolVican9e81c6a2017-02-09 13:09:07 +01007358 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007359 goto error;
7360 }
Michal Vasko10681e82018-01-16 14:54:16 +01007361
7362 /* remove our submodules from the parsed submodules list */
7363 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007364 } else {
7365 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007366 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007367
7368 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007369 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007370 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007371 }
7372
Michal Vasko44ab1462017-05-18 13:18:36 +02007373 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007374 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007375 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7376 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007377 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007378
7379error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007380 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007381 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007382
7383 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007384 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7385 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007386 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007387 return NULL;
7388 }
7389
Michal Vasko53b7da02018-02-13 15:28:42 +01007390 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007391
Radek Krejci9e757e02017-03-08 17:18:09 +01007392 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007393 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007394 lyp_del_includedup(module, 1);
7395 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007396 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007397}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007398
Radek Krejci37f9ba32017-02-10 16:50:35 +01007399/* logs directly */
7400struct lys_module *
7401yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7402{
7403 struct lyxml_elem *yin;
7404 struct lys_module *result;
7405
Radek Krejcie1bacd72017-03-01 13:18:46 +01007406 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007407 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007408 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007409 return NULL;
7410 }
7411
7412 result = yin_read_module_(ctx, yin, revision, implement);
7413
7414 lyxml_free(ctx, yin);
7415
7416 return result;
7417}
7418
Radek Krejcic1885952017-02-07 09:37:51 +01007419static int
7420yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007421 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007422 const char *true_val, const char *false_val, struct unres_schema *unres)
7423{
7424 uint8_t *val;
7425 const char *str;
7426 struct lyext_substmt *info;
7427
7428 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7429 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007430 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007431 return EXIT_FAILURE;
7432 }
7433 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007434 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007435 return EXIT_FAILURE;
7436 }
7437
Radek Krejcidb35f172017-02-27 11:03:01 +01007438 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007439 return EXIT_FAILURE;
7440 }
7441
7442 str = lyxml_get_attr(node, "value", NULL);
7443 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007444 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007445 } else if (true_val && !strcmp(true_val, str)) {
7446 /* true value */
7447 *val = 1;
7448 } else if (false_val && !strcmp(false_val, str)) {
7449 /* false value */
7450 *val = 2;
7451 } else {
7452 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007453 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007454 return EXIT_FAILURE;
7455 }
7456
7457 return EXIT_SUCCESS;
7458}
7459
Radek Krejci8d6b7422017-02-03 14:42:13 +01007460/*
7461 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7462 * argname - name of the element/attribute where the value is stored
7463 */
7464static int
7465yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007466 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007467 int argelem, const char *argname, struct unres_schema *unres)
7468{
7469 int c;
PavolVican99c70722017-02-18 17:25:52 +01007470 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007471 void *reallocated;
7472 struct lyext_substmt *info;
7473
7474 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7475 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007476 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007477 return EXIT_FAILURE;
7478 }
7479 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007480 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007481 return EXIT_FAILURE;
7482 }
7483
7484 c = 0;
7485 if (info->cardinality >= LY_STMT_CARD_SOME) {
7486 /* there can be multiple instances, str is actually const char *** */
7487 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007488 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007489 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007490 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007491 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007492 if (stmt == LY_STMT_BELONGSTO) {
7493 /* allocate another array for the belongs-to's prefixes */
7494 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007495 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007496 } else if (stmt == LY_STMT_ARGUMENT) {
7497 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007498 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007499 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007500 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007501 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007502 /* get the index in the array to add new item */
7503 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007504 }
Radek Krejci56c80412017-02-09 10:44:16 +01007505 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007506 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007507 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007508 return EXIT_FAILURE;
7509 }
7510
7511 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007512 str[c] = read_yin_subnode(mod->ctx, node, argname);
7513 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007514 return EXIT_FAILURE;
7515 }
Radek Krejci56c80412017-02-09 10:44:16 +01007516 } else {
7517 str[c] = lyxml_get_attr(node, argname, NULL);
7518 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007519 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007520 return EXIT_FAILURE;
7521 } else {
7522 str[c] = lydict_insert(mod->ctx, str[c], 0);
7523 }
7524
7525 if (stmt == LY_STMT_BELONGSTO) {
7526 /* get the belongs-to's mandatory prefix substatement */
7527 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007528 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007529 return EXIT_FAILURE;
7530 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007531 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007532 return EXIT_FAILURE;
7533 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007534 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007535 return EXIT_FAILURE;
7536 }
7537 /* and now finally get the value */
7538 if (p) {
7539 str = p[1];
7540 } else {
7541 str++;
7542 }
7543 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7544 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007545 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007546 return EXIT_FAILURE;
7547 }
7548 str[c] = lydict_insert(mod->ctx, str[c], 0);
7549
PavolVican6d400872017-03-01 15:19:18 +01007550 if (!str[c] || lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_PREFIX, c, unres)) {
Radek Krejci56c80412017-02-09 10:44:16 +01007551 return EXIT_FAILURE;
7552 }
PavolVican99c70722017-02-18 17:25:52 +01007553 } else if (stmt == LY_STMT_ARGUMENT) {
7554 str = (p) ? p[1] : str + 1;
7555 if (!node->child) {
7556 /* default value of yin element */
7557 ((uint8_t *)str)[c] = 2;
7558 } else {
7559 /* get optional yin-element substatement */
7560 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007561 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007562 return EXIT_FAILURE;
7563 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007564 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007565 return EXIT_FAILURE;
7566 } else {
7567 /* and now finally get the value */
7568 value = lyxml_get_attr(node->child, "value", NULL);
7569 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007570 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007571 return EXIT_FAILURE;
7572 }
7573 if (ly_strequal(value, "true", 0)) {
7574 ((uint8_t *)str)[c] = 1;
7575 } else if (ly_strequal(value, "false", 0)) {
7576 ((uint8_t *)str)[c] = 2;
7577 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007578 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007579 return EXIT_FAILURE;
7580 }
7581
7582 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7583 return EXIT_FAILURE;
7584 }
7585 }
7586 }
Radek Krejci56c80412017-02-09 10:44:16 +01007587 }
7588 }
7589 if (p) {
7590 /* enlarge the array(s) */
7591 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7592 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007593 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007594 lydict_remove(mod->ctx, p[0][c]);
7595 p[0][c] = NULL;
7596 return EXIT_FAILURE;
7597 }
7598 p[0] = reallocated;
7599 p[0][c + 1] = NULL;
7600
7601 if (stmt == LY_STMT_BELONGSTO) {
7602 /* enlarge the second belongs-to's array with prefixes */
7603 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7604 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007605 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007606 lydict_remove(mod->ctx, p[1][c]);
7607 p[1][c] = NULL;
7608 return EXIT_FAILURE;
7609 }
7610 p[1] = reallocated;
7611 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007612 } else if (stmt == LY_STMT_ARGUMENT){
7613 /* enlarge the second argument's array with yin element */
7614 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7615 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007616 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007617 ((uint8_t *)p[1])[c] = 0;
7618 return EXIT_FAILURE;
7619 }
7620 p[1] = reallocated;
7621 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007622 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007623 }
7624
7625 return EXIT_SUCCESS;
7626}
7627
7628static void *
7629yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7630 uint16_t mask)
7631{
7632 void *data;
7633 struct lyext_substmt *info;
7634
7635 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7636 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007637 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007638 return NULL;
7639 }
7640 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007641 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007642 return NULL;
7643 }
7644
7645 return data;
7646}
7647
Radek Krejcic1885952017-02-07 09:37:51 +01007648static int
7649yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007650 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007651 const char *val1_str, const char *val2_str, uint16_t mask,
7652 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7653{
7654 uint16_t *val;
7655 const char *str;
7656
7657 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7658 if (!val) {
7659 return EXIT_FAILURE;
7660 }
7661
7662 str = lyxml_get_attr(node, "value", NULL);
7663 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007664 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007665 } else if (!strcmp(val1_str, str)) {
7666 *val = *val | val1;
7667 } else if (!strcmp(val2_str, str)) {
7668 *val = *val | val2;
7669 } else {
7670 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007671 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007672 return EXIT_FAILURE;
7673 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007674 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007675 return EXIT_FAILURE;
7676 }
7677 return EXIT_SUCCESS;
7678}
7679
Radek Krejcif95b6292017-02-13 15:57:37 +01007680static struct lys_node **
7681yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7682{
7683 struct lyext_substmt *info;
7684 struct lys_node **snode, *siter;
7685
7686 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7687 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007688 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007689 return NULL;
7690 }
7691 if (info->cardinality < LY_STMT_CARD_SOME) {
7692 LY_TREE_FOR(*snode, siter) {
7693 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007694 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007695 return NULL;
7696 }
7697 }
7698 }
7699
7700 return snode;
7701}
7702
Radek Krejci8d6b7422017-02-03 14:42:13 +01007703static void **
7704yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7705{
7706 int c;
7707 void **data, ***p = NULL;
7708 void *reallocated;
7709 struct lyext_substmt *info;
7710
7711 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7712 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007713 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007714 return NULL;
7715 }
7716 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007717 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007718 return NULL;
7719 }
7720
7721 c = 0;
7722 if (info->cardinality >= LY_STMT_CARD_SOME) {
7723 /* there can be multiple instances, so instead of pointer to array,
7724 * we have in data pointer to pointer to array */
7725 p = (void ***)data;
7726 data = *p;
7727 if (!data) {
7728 /* allocate initial array */
7729 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007730 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007731 } else {
7732 for (c = 0; *data; data++, c++);
7733 }
7734 }
7735
7736 if (p) {
7737 /* enlarge the array */
7738 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007739 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007740 *p = reallocated;
7741 data = *p;
7742 data[c + 1] = NULL;
7743 }
7744
7745 return &data[c];
7746}
7747
7748int
7749lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7750 struct unres_schema *unres)
7751{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007752 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007753 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007754 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007755 const char *value, *name;
7756 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007757 struct lyext_substmt *info;
7758 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007759 long long int ll;
7760 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007761 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007762
Radek Krejcia8d111f2017-05-31 13:57:37 +02007763#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7764 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007765 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007766 (**(TYPE **)TO) = (TYPE)FROM;
7767
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007768#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007769 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7770 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007771 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007772 goto error; \
7773 } \
7774 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007775 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007776 goto error; \
7777 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007778 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007779 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7780 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007781 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007782 if (!(*pp)) { \
7783 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007784 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007785 } else { \
7786 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7787 } \
7788 p = &(*(TYPE**)pp)[i]; \
7789 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007790#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007791 if (pp) { \
7792 /* enlarge the array */ \
7793 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007794 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007795 *pp = reallocated; \
7796 (*(TYPE**)pp)[i + 1] = 0; \
7797 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007798#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7799 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7800 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007801 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007802#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7803 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007804 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007805 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007806 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007807 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7808 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7809 goto error; \
7810 } \
7811 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007812
Radek Krejci8d6b7422017-02-03 14:42:13 +01007813 LY_TREE_FOR_SAFE(yin->child, next, node) {
7814 if (!node->ns) {
7815 /* garbage */
7816 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7817 /* we have the extension's argument */
7818 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007819 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007820 goto error;
7821 }
7822 ext->arg_value = node->content;
7823 node->content = NULL;
7824 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7825 /* extension */
7826 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7827 goto error;
7828 }
7829 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007830 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007831 goto error;
7832 }
7833 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007834 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007835 goto error;
7836 }
7837 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007838 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007839 goto error;
7840 }
7841 } else if (!strcmp(node->name, "type")) {
7842 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7843 if (!type) {
7844 goto error;
7845 }
7846 /* allocate type structure */
7847 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007848 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007849
7850 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007851 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007852 (*type)->der = (struct lys_tpdf *)node;
7853 (*type)->parent = (struct lys_tpdf *)ext;
7854
7855 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7856 (*type)->der = NULL;
7857 goto error;
7858 }
7859 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007860 } else if (!strcmp(node->name, "typedef")) {
7861 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7862 if (!pp) {
7863 goto error;
7864 }
7865 /* allocate typedef structure */
7866 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007867 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007868
7869 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7870 goto error;
7871 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007872 } else if (!strcmp(node->name, "if-feature")) {
7873 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7874 if (!pp) {
7875 goto error;
7876 }
7877 /* allocate iffeature structure */
7878 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007879 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007880
7881 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7882 goto error;
7883 }
7884 } else if (!strcmp(node->name, "status")) {
7885 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7886 if (!p) {
7887 goto error;
7888 }
7889
Michal Vasko53b7da02018-02-13 15:28:42 +01007890 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007891 if (!strcmp(value, "current")) {
7892 *(uint16_t*)p |= LYS_STATUS_CURR;
7893 } else if (!strcmp(value, "deprecated")) {
7894 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7895 } else if (!strcmp(value, "obsolete")) {
7896 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7897 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007898 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007899 goto error;
7900 }
7901
7902 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7903 goto error;
7904 }
Radek Krejcic1885952017-02-07 09:37:51 +01007905 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007906 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007907 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007908 goto error;
7909 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007910 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007911 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007912 goto error;
7913 }
7914 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007915 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007916 goto error;
7917 }
Radek Krejcic1885952017-02-07 09:37:51 +01007918 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007919 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007920 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7921 goto error;
7922 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007923 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007924 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007925 goto error;
7926 }
7927 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007928 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007929 goto error;
7930 }
7931 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007932 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007933 goto error;
7934 }
7935 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007936 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007937 goto error;
7938 }
7939 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007940 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007941 goto error;
7942 }
7943 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007944 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007945 goto error;
7946 }
7947 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007948 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007949 goto error;
7950 }
7951 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007952 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007953 goto error;
7954 }
Radek Krejcic1885952017-02-07 09:37:51 +01007955 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007956 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7957 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007958 goto error;
7959 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007960 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007961 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007962 goto error;
7963 }
7964 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007965 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007966 goto error;
7967 }
7968 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007969 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007970 goto error;
7971 }
7972 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007973 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007974 goto error;
7975 }
Radek Krejcic1885952017-02-07 09:37:51 +01007976 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007977 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007978 goto error;
7979 }
7980 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007981 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007982 goto error;
7983 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007984 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007985 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007986
Michal Vasko53b7da02018-02-13 15:28:42 +01007987 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007988 v = strtol(value, NULL, 10);
7989
7990 /* range check */
7991 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007992 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007993 goto error;
7994 }
7995
7996 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7997 goto error;
7998 }
7999
8000 /* store the value */
8001 (*(uint8_t *)p) = (uint8_t)v;
8002
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008003 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008004 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008005 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008006
Michal Vasko53b7da02018-02-13 15:28:42 +01008007 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008008 while (isspace(value[0])) {
8009 value++;
8010 }
8011
8012 if (!strcmp(value, "unbounded")) {
8013 u = 0;
8014 } else {
8015 /* convert it to uint32_t */
8016 errno = 0; endptr = NULL;
8017 u = strtoul(value, &endptr, 10);
8018 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008019 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008020 goto error;
8021 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008022 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008023
8024 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8025 goto error;
8026 }
8027
8028 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008029 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008030
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008031 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008032 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008033 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008034
Michal Vasko53b7da02018-02-13 15:28:42 +01008035 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008036 while (isspace(value[0])) {
8037 value++;
8038 }
8039
8040 /* convert it to uint32_t */
8041 errno = 0;
8042 endptr = NULL;
8043 u = strtoul(value, &endptr, 10);
8044 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008045 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008046 goto error;
8047 }
8048
8049 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8050 goto error;
8051 }
8052
8053 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008054 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008055
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008056 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008057 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008058 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8059
Michal Vasko53b7da02018-02-13 15:28:42 +01008060 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008061 while (isspace(value[0])) {
8062 value++;
8063 }
8064
8065 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008066 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008067
8068 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008069 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008070 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008071 goto error;
8072 }
8073
8074 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8075 goto error;
8076 }
8077
8078 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008079 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008080
8081 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008082 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008083 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008084
Michal Vasko53b7da02018-02-13 15:28:42 +01008085 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008086 ll = strtoll(value, NULL, 10);
8087
8088 /* range check */
8089 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008090 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008091 goto error;
8092 }
8093
8094 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8095 goto error;
8096 }
8097
8098 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008099 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008100
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008101 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008102 } else if (!strcmp(node->name, "module")) {
8103 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8104 if (!pp) {
8105 goto error;
8106 }
8107
8108 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8109 if (!(*pp)) {
8110 goto error;
8111 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008112 } else if (!strcmp(node->name, "when")) {
8113 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8114
8115 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8116 if (!*(struct lys_when**)p) {
8117 goto error;
8118 }
8119
8120 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008121 } else if (!strcmp(node->name, "revision")) {
8122 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8123
8124 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008125 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008126 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8127 goto error;
8128 }
8129
8130 /* check uniqueness of the revision dates - not required by RFC */
8131 if (pp) {
8132 for (j = 0; j < i; j++) {
8133 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008134 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008135 }
8136 }
8137 }
8138
8139 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008140 } else if (!strcmp(node->name, "unique")) {
8141 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8142
8143 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008144 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008145 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8146 goto error;
8147 }
8148
8149 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8150 goto error;
8151 }
8152 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008153 } else if (!strcmp(node->name, "action")) {
8154 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8155 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008156 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008157 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008158 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008159 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008160 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008161 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008162 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008163 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008164 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008165 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008166 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008167 } else if (!strcmp(node->name, "output")) {
8168 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8169 } else if (!strcmp(node->name, "input")) {
8170 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8171 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008172 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008173 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008174 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008175 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008176 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008177 } else if (!strcmp(node->name, "notification")) {
8178 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8179 } else if (!strcmp(node->name, "uses")) {
8180 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008181 } else if (!strcmp(node->name, "length")) {
8182 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8183 } else if (!strcmp(node->name, "must")) {
8184 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8185 if (!pp) {
8186 goto error;
8187 }
8188 /* allocate structure for must */
8189 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008190 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008191
8192 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8193 goto error;
8194 }
8195 } else if (!strcmp(node->name, "pattern")) {
8196 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008197 GETVAL(mod->ctx, value, node, "value");
8198 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008199 goto error;
8200 }
8201
8202 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008203 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008204 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
8205
8206 modifier = 0x06; /* ACK */
8207 if (mod->version >= 2) {
8208 name = NULL;
8209 LY_TREE_FOR(node->child, child) {
8210 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8211 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008212 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008213 goto error;
8214 }
8215
Michal Vasko53b7da02018-02-13 15:28:42 +01008216 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008217 if (!strcmp(name, "invert-match")) {
8218 modifier = 0x15; /* NACK */
8219 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008220 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008221 goto error;
8222 }
8223 /* get extensions of the modifier */
8224 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8225 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8226 goto error;
8227 }
8228 }
8229 }
8230 }
8231
8232 /* store the value: modifier byte + value + terminating NULL byte */
8233 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008234 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008235 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8236 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8237 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8238
8239 /* get possible sub-statements */
8240 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8241 goto error;
8242 }
8243
8244 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8245 } else if (!strcmp(node->name, "range")) {
8246 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008247 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008248 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008249 }
8250 lyxml_free(mod->ctx, node);
8251 }
8252
PavolVicanc4b798e2017-02-20 23:15:27 +01008253 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8254 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008255 }
8256
Radek Krejci8d6b7422017-02-03 14:42:13 +01008257 return EXIT_SUCCESS;
8258
8259error:
8260 return EXIT_FAILURE;
8261}