blob: c40a07a2b1a87ffc7c259641dfbb572c1d4e0724 [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"
Michal Vasko6c810702018-03-14 16:23:21 +010028#include "hash_table.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
Michal Vasko101658e2018-06-05 15:05:54 +0200587 if (type->value_flags & LY_VALUE_UNRESGRP) {
Radek Krejcic13db382016-08-16 10:52:42 +0200588 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Michal Vasko70bf8e52018-03-26 11:32:33 +0200589 * unresolved item left inside the grouping, LYTYPE_GRP 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 }
Michal Vasko101658e2018-06-05 15:05:54 +0200598 type->value_flags &= ~LY_VALUE_UNRESGRP;
Radek Krejcic13db382016-08-16 10:52:42 +0200599 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200600 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200601
Radek Krejcicf509982015-12-15 09:22:44 +0100602 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100603 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Michal Vasko53b7da02018-02-13 15:28:42 +0100604 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100605 return -1;
606 }
607
Radek Krejcie534c132016-11-23 13:32:31 +0100608 /* parse extension instances */
609 LY_TREE_FOR_SAFE(yin->child, next, node) {
610 if (!node->ns) {
611 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100612 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100613 continue;
614 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
615 /* YANG (YIN) statements - process later */
616 continue;
617 }
618
Michal Vasko53b7da02018-02-13 15:28:42 +0100619 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, type->ext_size, "extensions", "type", error);
Radek Krejcidce5f972017-09-12 15:47:49 +0200620
Michal Vasko53b7da02018-02-13 15:28:42 +0100621 lyxml_unlink_elem(ctx, node, 2);
622 lyxml_add_child(ctx, &exts, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100623 c_ext++;
624 }
625 if (c_ext) {
626 type->ext = calloc(c_ext, sizeof *type->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100627 LY_CHECK_ERR_GOTO(!type->ext, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200628
Radek Krejcie534c132016-11-23 13:32:31 +0100629 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100630 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 +0100631 type->ext_size++;
632 if (rc) {
633 goto error;
634 }
635 }
636 }
637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200640 /* RFC 6020 9.7.4 - bit */
641
642 /* get bit specifications, at least one must be present */
643 LY_TREE_FOR_SAFE(yin->child, next, node) {
644 if (!strcmp(node->name, "bit")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100645 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.bits.count, type->info.bits.count, "bits", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200646 type->info.bits.count = 0; goto error);
Radek Krejci994b6f62015-06-18 16:47:27 +0200647 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200648 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100649 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200650 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200651 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200652 }
653 }
Radek Krejcie663e012016-08-01 17:12:34 +0200654 dertype = &type->der->type;
655 if (!dertype->der) {
656 if (!type->info.bits.count) {
657 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100658 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200659 goto error;
660 }
661 } else {
662 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
663 if (module->version < 2 && type->info.bits.count) {
664 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
665 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100666 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200667 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200668 goto error;
669 }
Radek Krejciac781922015-07-09 15:35:14 +0200670 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200671
672 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +0100673 LY_CHECK_ERR_GOTO(!type->info.bits.bit, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200674
Radek Krejci73adb602015-07-02 18:07:40 +0200675 p = 0;
676 i = -1;
677 LY_TREE_FOR(yin->child, next) {
678 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200679 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200680
Michal Vasko53b7da02018-02-13 15:28:42 +0100681 GETVAL(ctx, value, next, "name");
682 if (lyp_check_identifier(ctx, value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100683 goto error;
684 }
685
Michal Vasko53b7da02018-02-13 15:28:42 +0100686 type->info.bits.bit[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100687 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 +0200688 type->info.bits.count = i + 1;
689 goto error;
690 }
691
Radek Krejcie663e012016-08-01 17:12:34 +0200692 if (!dertype->der) { /* directly derived type from bits built-in type */
693 /* check the name uniqueness */
694 for (j = 0; j < i; j++) {
695 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100696 LOGVAL(ctx, LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejcie663e012016-08-01 17:12:34 +0200697 type->info.bits.count = i + 1;
698 goto error;
699 }
700 }
701 } else {
702 /* restricted bits type - the name MUST be used in the base type */
703 bits_sc = dertype->info.bits.bit;
704 for (j = 0; j < dertype->info.bits.count; j++) {
705 if (ly_strequal(bits_sc[j].name, value, 1)) {
706 break;
707 }
708 }
709 if (j == dertype->info.bits.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100710 LOGVAL(ctx, LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200711 type->info.bits.count = i + 1;
712 goto error;
713 }
714 }
715
Radek Krejcie663e012016-08-01 17:12:34 +0200716
Radek Krejci0d70c372015-07-02 16:23:10 +0200717 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100718 LY_TREE_FOR_SAFE(next->child, next2, node) {
719 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200720 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200721 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100722 } else if (strcmp(node->ns->value, LY_NSYIN)) {
723 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100724 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Michal Vasko53b7da02018-02-13 15:28:42 +0100725 LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci9b15fea2017-01-23 11:31:43 +0100726 goto error;
727 }
728 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200729 if (p_ != -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100730 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +0200731 type->info.bits.count = i + 1;
732 goto error;
733 }
734
Michal Vasko53b7da02018-02-13 15:28:42 +0100735 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200736 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200737
738 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200739 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100740 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200741 type->info.bits.count = i + 1;
742 goto error;
743 }
744 type->info.bits.bit[i].pos = (uint32_t)p_;
745
Radek Krejcie663e012016-08-01 17:12:34 +0200746 if (!dertype->der) { /* directly derived type from bits built-in type */
747 /* keep the highest enum value for automatic increment */
748 if (type->info.bits.bit[i].pos >= p) {
749 p = type->info.bits.bit[i].pos;
750 p++;
751 } else {
752 /* check that the value is unique */
753 for (j = 0; j < i; j++) {
754 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100755 LOGVAL(ctx, LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +0200756 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
757 type->info.bits.bit[j].name);
758 type->info.bits.count = i + 1;
759 goto error;
760 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200761 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200762 }
763 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200764
Radek Krejci8d6b7422017-02-03 14:42:13 +0100765 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100766 LYEXT_SUBSTMT_POSITION, 0, unres)) {
767 goto error;
768 }
PavolVican92f23622017-12-12 13:35:56 +0100769
PavolVican0144fae2018-02-05 15:54:17 +0100770 for (j = 0; j < type->info.bits.bit[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100771 /* set flag, which represent LYEXT_OPT_VALID */
772 if (type->info.bits.bit[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100773 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100774 break;
775 }
776 }
777
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200778 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100779 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 +0200780 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200781 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100782 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200783 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200784 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200785 }
Radek Krejcie663e012016-08-01 17:12:34 +0200786
787 if (!dertype->der) { /* directly derived type from bits built-in type */
788 if (p_ == -1) {
789 /* assign value automatically */
790 if (p > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100791 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejcie663e012016-08-01 17:12:34 +0200792 type->info.bits.count = i + 1;
793 goto error;
794 }
795 type->info.bits.bit[i].pos = (uint32_t)p;
796 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
797 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200798 }
Radek Krejcie663e012016-08-01 17:12:34 +0200799 } else { /* restricted bits type */
800 if (p_ == -1) {
801 /* automatically assign position from base type */
802 type->info.bits.bit[i].pos = bits_sc[j].pos;
803 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
804 } else {
805 /* check that the assigned position corresponds to the original
806 * position of the bit in the base type */
807 if (p_ != bits_sc[j].pos) {
808 /* p_ - assigned position in restricted bits
809 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100810 LOGVAL(ctx, LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200811 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200812 type->info.bits.count = i + 1;
813 goto error;
814 }
815 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200816 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200817
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200818 /* if-features */
819 if (c_ftrs) {
820 bits_sc = &type->info.bits.bit[i];
821 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
822 if (!bits_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100823 LOGMEM(ctx);
Radek Krejci994b6f62015-06-18 16:47:27 +0200824 type->info.bits.count = i + 1;
825 goto error;
826 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200827
828 LY_TREE_FOR(next->child, node) {
829 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200830 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200831 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
832 bits_sc->iffeature_size++;
833 if (rc) {
834 type->info.bits.count = i + 1;
835 goto error;
836 }
837 }
838 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200839 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200840
841 /* keep them ordered by position */
842 j = i;
843 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
844 /* switch them */
845 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
846 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
847 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
848 j--;
849 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200850 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200851 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200854 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200855 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200856
Radek Krejcif9401c32015-06-26 16:47:36 +0200857 if (!strcmp(node->name, "range")) {
858 if (type->info.dec64.range) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100859 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200860 goto error;
861 }
862
Michal Vasko53b7da02018-02-13 15:28:42 +0100863 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200864 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko53b7da02018-02-13 15:28:42 +0100865 LY_CHECK_ERR_GOTO(!type->info.dec64.range, LOGMEM(ctx), error);
866 type->info.dec64.range->expr = lydict_insert(ctx, value, 0);
Radek Krejcif9401c32015-06-26 16:47:36 +0200867
868 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100869 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200870 goto error;
871 }
PavolVican0144fae2018-02-05 15:54:17 +0100872 for (j = 0; j < type->info.dec64.range->ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100873 /* set flag, which represent LYEXT_OPT_VALID */
874 if (type->info.dec64.range->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100875 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100876 break;
877 }
878 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200879 } else if (!strcmp(node->name, "fraction-digits")) {
880 if (type->info.dec64.dig) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100881 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200882 goto error;
883 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100884 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200885 v = strtol(value, NULL, 10);
886
887 /* range check */
888 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100889 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200890 goto error;
891 }
892 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200893 type->info.dec64.div = 10;
894 for (i = 1; i < v; i++) {
895 type->info.dec64.div *= 10;
896 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100897
898 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100899 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100900 goto error;
901 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200902 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100903 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200904 goto error;
905 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200906 }
907
908 /* mandatory sub-statement(s) check */
909 if (!type->info.dec64.dig && !type->der->type.der) {
910 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vasko53b7da02018-02-13 15:28:42 +0100911 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200912 goto error;
913 }
Radek Krejci7511f402015-07-10 09:56:30 +0200914 if (type->info.dec64.dig && type->der->type.der) {
915 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vasko53b7da02018-02-13 15:28:42 +0100916 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200917 goto error;
918 }
Radek Krejci4800f652016-09-08 14:02:52 +0200919
920 /* copy fraction-digits specification from parent type for easier internal use */
921 if (type->der->type.der) {
922 type->info.dec64.dig = type->der->type.info.dec64.dig;
923 type->info.dec64.div = type->der->type.info.dec64.div;
924 }
925
Michal Vasko53b7da02018-02-13 15:28:42 +0100926 if (type->info.dec64.range && lyp_check_length_range(ctx, type->info.dec64.range->expr, type)) {
927 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200928 goto error;
929 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200933 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200934
Radek Krejci994b6f62015-06-18 16:47:27 +0200935 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 if (!strcmp(node->name, "enum")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100939 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.enums.count, type->info.enums.count, "enums", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200940 type->info.enums.count = 0; goto error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200942 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100943 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200944 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200945 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 }
947 }
Radek Krejcie663e012016-08-01 17:12:34 +0200948 dertype = &type->der->type;
949 if (!dertype->der) {
950 if (!type->info.enums.count) {
951 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100952 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200953 goto error;
954 }
955 } else {
956 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
957 if (module->version < 2 && type->info.enums.count) {
958 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
959 * 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 +0100960 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200961 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200962 goto error;
963 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200964 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200965
Radek Krejci1574a8d2015-08-03 14:16:52 +0200966 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +0100967 LY_CHECK_ERR_GOTO(!type->info.enums.enm, LOGMEM(ctx), error);
Radek Krejcifc8d8322016-06-24 11:23:23 +0200968
Radek Krejcie663e012016-08-01 17:12:34 +0200969 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200970 i = -1;
971 LY_TREE_FOR(yin->child, next) {
972 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200973 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200974
Michal Vasko53b7da02018-02-13 15:28:42 +0100975 GETVAL(ctx, value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100976 if (!value[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100977 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
978 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100979 goto error;
980 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100981 type->info.enums.enm[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100982 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 +0200983 type->info.enums.count = i + 1;
984 goto error;
985 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200988 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100990 LOGVAL(ctx, LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 type->info.enums.count = i + 1;
992 goto error;
993 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200994
Radek Krejcie663e012016-08-01 17:12:34 +0200995 if (!dertype->der) { /* directly derived type from enumeration built-in type */
996 /* check the name uniqueness */
997 for (j = 0; j < i; j++) {
998 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100999 LOGVAL(ctx, LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
Radek Krejcie663e012016-08-01 17:12:34 +02001000 type->info.enums.count = i + 1;
1001 goto error;
1002 }
1003 }
1004 } else {
1005 /* restricted enumeration type - the name MUST be used in the base type */
1006 enms_sc = dertype->info.enums.enm;
1007 for (j = 0; j < dertype->info.enums.count; j++) {
1008 if (ly_strequal(enms_sc[j].name, value, 1)) {
1009 break;
1010 }
1011 }
1012 if (j == dertype->info.enums.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001013 LOGVAL(ctx, LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001014 type->info.enums.count = i + 1;
1015 goto error;
1016 }
1017 }
Radek Krejci04581c62015-05-22 21:24:00 +02001018
Radek Krejcie663e012016-08-01 17:12:34 +02001019 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001020 LY_TREE_FOR_SAFE(next->child, next2, node) {
1021 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001022 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001023 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001024 } else if (strcmp(node->ns->value, LY_NSYIN)) {
1025 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001026 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001027 LYEXT_SUBSTMT_SELF, 0, unres)) {
1028 goto error;
1029 }
1030 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +02001031 if (val_set) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001032 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +02001033 type->info.enums.count = i + 1;
1034 goto error;
1035 }
1036
Michal Vasko53b7da02018-02-13 15:28:42 +01001037 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +02001038 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +02001039
1040 /* range check */
1041 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001042 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +02001043 type->info.enums.count = i + 1;
1044 goto error;
1045 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001046 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +02001047
Radek Krejcie663e012016-08-01 17:12:34 +02001048 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001049 if (!i) {
1050 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001051 v = type->info.enums.enm[i].value;
1052 v++;
1053 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001054 /* keep the highest enum value for automatic increment */
1055 if (type->info.enums.enm[i].value >= v) {
1056 v = type->info.enums.enm[i].value;
1057 v++;
1058 } else {
1059 /* check that the value is unique */
1060 for (j = 0; j < i; j++) {
1061 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001062 LOGVAL(ctx, LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican5de389c2016-08-30 08:55:15 +02001063 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1064 type->info.enums.enm[j].name);
1065 type->info.enums.count = i + 1;
1066 goto error;
1067 }
Radek Krejcie663e012016-08-01 17:12:34 +02001068 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001069 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070 }
1071 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001072 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001073
Radek Krejci8d6b7422017-02-03 14:42:13 +01001074 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001075 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1076 goto error;
1077 }
PavolVican92f23622017-12-12 13:35:56 +01001078
PavolVican0144fae2018-02-05 15:54:17 +01001079 for (j = 0; j < type->info.enums.enm[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +01001080 /* set flag, which represent LYEXT_OPT_VALID */
1081 if (type->info.enums.enm[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001082 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001083 break;
1084 }
1085 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001086 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001087 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 +02001088 c_ftrs++;
1089
Radek Krejci0d70c372015-07-02 16:23:10 +02001090 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001091 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001092 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001094 }
Radek Krejcie663e012016-08-01 17:12:34 +02001095
1096 if (!dertype->der) { /* directly derived type from enumeration */
1097 if (!val_set) {
1098 /* assign value automatically */
1099 if (v > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001100 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejcie663e012016-08-01 17:12:34 +02001101 type->info.enums.count = i + 1;
1102 goto error;
1103 }
1104 type->info.enums.enm[i].value = v;
1105 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1106 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 }
Radek Krejcie663e012016-08-01 17:12:34 +02001108 } else { /* restricted enum type */
1109 if (!val_set) {
1110 /* automatically assign value from base type */
1111 type->info.enums.enm[i].value = enms_sc[j].value;
1112 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1113 } else {
1114 /* check that the assigned value corresponds to the original
1115 * value of the enum in the base type */
1116 if (v_ != enms_sc[j].value) {
1117 /* v_ - assigned value in restricted enum
1118 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001119 LOGVAL(ctx, LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001120 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001121 type->info.enums.count = i + 1;
1122 goto error;
1123 }
1124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001126
1127 /* if-features */
1128 if (c_ftrs) {
1129 enms_sc = &type->info.enums.enm[i];
1130 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1131 if (!enms_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001132 LOGMEM(ctx);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 type->info.enums.count = i + 1;
1134 goto error;
1135 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001136
1137 LY_TREE_FOR(next->child, node) {
1138 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001139 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001140 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1141 enms_sc->iffeature_size++;
1142 if (rc) {
1143 type->info.enums.count = i + 1;
1144 goto error;
1145 }
1146 }
1147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 }
1151 break;
1152
1153 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001154 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155
Michal Vaskof2d43962016-09-02 11:10:16 +02001156 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001157 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001158
Michal Vaskoe29c6622015-11-27 15:02:31 +01001159 if (strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001160 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001161 goto error;
1162 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001163
Michal Vasko53b7da02018-02-13 15:28:42 +01001164 GETVAL(ctx, value, yin->child, "name");
Michal Vaskof2d43962016-09-02 11:10:16 +02001165 /* store in the JSON format */
1166 value = transform_schema2json(module, value);
1167 if (!value) {
1168 goto error;
1169 }
1170 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Michal Vasko53b7da02018-02-13 15:28:42 +01001171 lydict_remove(ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001172 if (rc == -1) {
1173 goto error;
1174 }
Radek Krejci18a44882017-01-23 13:47:29 +01001175
Radek Krejci8d6b7422017-02-03 14:42:13 +01001176 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001177 goto error;
1178 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001179 }
1180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001181 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001182 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001183 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001184 break;
1185 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001186 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001188 } else {
1189 if (type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001190 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
Pavol Vicanf0046f42016-09-07 15:11:09 +02001191 goto error;
1192 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 if (yin->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001195 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001196 goto error;
1197 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198 break;
1199
1200 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001201 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001202 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001203
Radek Krejciaf351422015-06-19 14:49:38 +02001204 if (!strcmp(node->name, "require-instance")) {
1205 if (type->info.inst.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001206 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001207 goto error;
1208 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001209 GETVAL(ctx, value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001210 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001211 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001212 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001213 type->info.inst.req = -1;
1214 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001215 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001216 goto error;
1217 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001218
1219 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001220 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001221 goto error;
1222 }
Radek Krejciaf351422015-06-19 14:49:38 +02001223 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001224 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001225 goto error;
1226 }
Radek Krejciaf351422015-06-19 14:49:38 +02001227 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001229 break;
1230
Radek Krejcif2860132015-06-20 12:37:20 +02001231 case LY_TYPE_BINARY:
1232 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001233 case LY_TYPE_INT8:
1234 case LY_TYPE_INT16:
1235 case LY_TYPE_INT32:
1236 case LY_TYPE_INT64:
1237 case LY_TYPE_UINT8:
1238 case LY_TYPE_UINT16:
1239 case LY_TYPE_UINT32:
1240 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001241 /* RFC 6020 9.2.4 - range */
1242
1243 /* length and range are actually the same restriction, so process
1244 * them by this common code, we just need to differ the name and
1245 * structure where the information will be stored
1246 */
1247 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001248 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001249 name = "length";
1250 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001251 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001252 name = "range";
1253 }
1254
Radek Krejci73adb602015-07-02 18:07:40 +02001255 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001256
Radek Krejcif2860132015-06-20 12:37:20 +02001257 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001258 if (*restrs) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001259 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001260 goto error;
1261 }
1262
Michal Vasko53b7da02018-02-13 15:28:42 +01001263 GETVAL(ctx, value, node, "value");
1264 if (lyp_check_length_range(ctx, value, type)) {
1265 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001266 goto error;
1267 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001268 *restrs = calloc(1, sizeof **restrs);
Michal Vasko53b7da02018-02-13 15:28:42 +01001269 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM(ctx), error);
1270 (*restrs)->expr = lydict_insert(ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001271
1272 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001273 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001274 goto error;
1275 }
PavolVican92f23622017-12-12 13:35:56 +01001276
1277 for (j = 0; j < (*restrs)->ext_size; ++j) {
1278 /* set flag, which represent LYEXT_OPT_VALID */
1279 if ((*restrs)->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001280 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001281 break;
1282 }
1283 }
Radek Krejcif2860132015-06-20 12:37:20 +02001284 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001285 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001286 goto error;
1287 }
Radek Krejcif2860132015-06-20 12:37:20 +02001288 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001289 break;
1290
1291 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001292 /* flag resolving for later use */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001293 if (!parenttype) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001294 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1295 if (siter) {
1296 /* just a flag - do not resolve */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001297 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001298 }
1299 }
1300
Radek Krejcidc4c1412015-06-19 15:39:54 +02001301 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001302 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001303
Michal Vasko88c29542015-11-27 14:57:53 +01001304 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001305 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001306 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001307 goto error;
1308 }
1309
Michal Vasko53b7da02018-02-13 15:28:42 +01001310 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001311 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001312 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001313 if (!type->info.lref.path) {
1314 goto error;
1315 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001316
1317 /* try to resolve leafref path only when this is instantiated
1318 * leaf, so it is not:
1319 * - typedef's type,
1320 * - in grouping definition,
1321 * - just instantiated in a grouping definition,
1322 * because in those cases the nodes referenced in path might not be present
1323 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001324 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001325 goto error;
1326 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001327
1328 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001329 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001330 goto error;
1331 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001332 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001333 if (type->info.lref.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001334 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001335 goto error;
1336 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001337 GETVAL(ctx, value, node, "value");
Michal Vasko08ae53e2016-09-02 12:40:04 +02001338 if (!strcmp(value, "true")) {
1339 type->info.lref.req = 1;
1340 } else if (!strcmp(value, "false")) {
1341 type->info.lref.req = -1;
1342 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001343 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001344 goto error;
1345 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001346
1347 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001348 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001349 goto error;
1350 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001351 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001352 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001353 goto error;
1354 }
Radek Krejci73adb602015-07-02 18:07:40 +02001355 }
1356
Radek Krejci742be352016-07-17 12:18:54 +02001357 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001358 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001359 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001360 goto error;
1361 } else {
1362 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001363 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001364 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001365 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001366 goto error;
1367 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001368 }
Radek Krejci742be352016-07-17 12:18:54 +02001369 }
1370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001371 break;
1372
1373 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001374 /* RFC 6020 9.4.4 - length */
1375 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001376 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001377 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001378
Radek Krejci3733a802015-06-19 13:43:21 +02001379 if (!strcmp(node->name, "length")) {
1380 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001381 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001382 goto error;
1383 }
1384
Michal Vasko53b7da02018-02-13 15:28:42 +01001385 GETVAL(ctx, value, node, "value");
1386 if (lyp_check_length_range(ctx, value, type)) {
1387 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001388 goto error;
1389 }
1390 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001391 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1392 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001393
Radek Krejci5fbc9162015-06-19 14:11:11 +02001394 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001395 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001396 goto error;
1397 }
PavolVican92f23622017-12-12 13:35:56 +01001398
1399 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1400 /* set flag, which represent LYEXT_OPT_VALID */
1401 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001402 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001403 break;
1404 }
1405 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001406 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001407 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001408 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001409 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001410 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001411 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001412 goto error;
1413 }
1414 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001415 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001416 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001417 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001418 in_grp = 1;
1419 }
Radek Krejci73adb602015-07-02 18:07:40 +02001420 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001421 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001422#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001423 if (!in_grp) {
1424 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001425 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001426 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001427 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001428#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001429 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001430 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001431
Michal Vasko53b7da02018-02-13 15:28:42 +01001432 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vaskofcd974b2017-08-22 10:17:49 +02001433 if (in_grp) {
1434 /* in grouping, just check the pattern syntax */
Michal Vasko53b7da02018-02-13 15:28:42 +01001435 if (lyp_check_pattern(ctx, value, NULL)) {
Michal Vaskofcd974b2017-08-22 10:17:49 +02001436 goto error;
1437 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001438 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001439#ifdef LY_ENABLED_CACHE
1440 else {
1441 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
Michal Vaskoa26db302018-02-14 15:22:10 +01001442 if (lyp_precompile_pattern(ctx, value,
Michal Vaskofcd974b2017-08-22 10:17:49 +02001443 (pcre**)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1444 (pcre_extra**)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1445 goto error;
1446 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001447 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001448#endif
Michal Vasko69068852015-07-13 14:34:31 +02001449 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001450 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001451 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001452
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001453 modifier = 0x06; /* ACK */
1454 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001455 if (module->version >= 2) {
1456 LY_TREE_FOR_SAFE(node->child, next2, child) {
1457 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1458 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001459 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001460 goto error;
1461 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001462
Michal Vasko53b7da02018-02-13 15:28:42 +01001463 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001464 if (!strcmp(name, "invert-match")) {
1465 modifier = 0x15; /* NACK */
1466 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001467 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001468 goto error;
1469 }
1470 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001471 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001472 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1473 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001474 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001475
Michal Vasko53b7da02018-02-13 15:28:42 +01001476 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001477 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001478 }
1479 }
1480
1481 len = strlen(value);
1482 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001483 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001484 buf[0] = modifier;
1485 strcpy(&buf[1], value);
1486
Michal Vasko53b7da02018-02-13 15:28:42 +01001487 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001488
1489 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001490 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001491 goto error;
1492 }
PavolVican92f23622017-12-12 13:35:56 +01001493
1494 for (j = 0; j < restr->ext_size; ++j) {
1495 /* set flag, which represent LYEXT_OPT_VALID */
1496 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001497 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001498 break;
1499 }
1500 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001501 }
1502 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001503 break;
1504
1505 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001506 /* RFC 6020 7.4 - type */
1507 /* count number of types in union */
1508 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001509 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001510
Radek Krejcie4c366b2015-07-02 10:11:31 +02001511 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001512 if (type->der->type.der) {
1513 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001514 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001515 goto error;
1516 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001517 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001518 i++;
1519 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001520 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001521 goto error;
1522 }
1523 }
1524
Radek Krejci038d5d92016-09-12 15:07:15 +02001525 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001526 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001527 goto error;
1528 }
1529
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001530 /* inherit instid presence information */
1531 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1532 type->info.uni.has_ptr_type = 1;
1533 }
1534
Radek Krejcie4c366b2015-07-02 10:11:31 +02001535 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001536 if (i) {
1537 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001538 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001539 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001540
Radek Krejcie4c366b2015-07-02 10:11:31 +02001541 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001542 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001543 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001544 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001545 if (!rc) {
1546 type->info.uni.count++;
1547
Radek Krejci7de36cf2016-09-12 16:18:50 +02001548 if (module->version < 2) {
1549 /* union's type cannot be empty or leafref */
1550 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001551 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001552 rc = -1;
1553 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001554 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001555 rc = -1;
1556 }
Michal Vasko88c29542015-11-27 14:57:53 +01001557 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001558
1559 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001560 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1561 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1562 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001563 type->info.uni.has_ptr_type = 1;
1564 }
Michal Vasko88c29542015-11-27 14:57:53 +01001565 }
1566 if (rc) {
1567 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1568 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001569 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001570 }
1571 free(type->info.uni.types);
1572 type->info.uni.types = NULL;
1573 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001574 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001575 type->der = NULL;
1576 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001577
1578 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001579 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001580 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001581 goto error;
1582 }
Michal Vasko88c29542015-11-27 14:57:53 +01001583 }
1584 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001585
Michal Vasko88c29542015-11-27 14:57:53 +01001586 case LY_TYPE_BOOL:
1587 case LY_TYPE_EMPTY:
1588 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001589 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001590 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001591 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001592 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 break;
1594
1595 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001596 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001597 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001598 }
1599
PavolVican92f23622017-12-12 13:35:56 +01001600 for(j = 0; j < type->ext_size; ++j) {
1601 /* set flag, which represent LYEXT_OPT_VALID */
1602 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001603 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001604 break;
1605 }
1606 }
1607
1608 /* if derived type has extension, which need validate data */
1609 dertype = &type->der->type;
1610 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001611 if (dertype->parent->flags & LYS_VALID_EXT) {
1612 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001613 }
1614 dertype = &dertype->der->type;
1615 }
1616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001617 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001618
1619error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001620 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001621 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001622}
1623
Michal Vasko0d343d12015-08-24 14:57:36 +02001624/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001626fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1627 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001628{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001630 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001631 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001632 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001633 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001634
Michal Vasko53b7da02018-02-13 15:28:42 +01001635 GETVAL(ctx, value, yin, "name");
1636 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001637 goto error;
1638 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001639 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001642 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001643 goto error;
1644 }
Radek Krejcieac35532015-05-31 19:09:15 +02001645
Michal Vasko88c29542015-11-27 14:57:53 +01001646 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001647 if (strcmp(node->ns->value, LY_NSYIN)) {
1648 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001649 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001650 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001651 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001652 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001653 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001654 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655 goto error;
1656 }
Michal Vasko88c29542015-11-27 14:57:53 +01001657 /* HACK for unres */
1658 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001659 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001660 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001661 goto error;
1662 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001663 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001664
Radek Krejci07d0fb92017-01-13 14:11:05 +01001665 /* 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 +01001666 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 } else if (!strcmp(node->name, "default")) {
1668 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001669 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 goto error;
1671 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001672 GETVAL(ctx, value, node, "value");
1673 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001674
Radek Krejci8d6b7422017-02-03 14:42:13 +01001675 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001676 goto error;
1677 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 } else if (!strcmp(node->name, "units")) {
1679 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001680 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 goto error;
1682 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001683 GETVAL(ctx, value, node, "name");
1684 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001685
Radek Krejci8d6b7422017-02-03 14:42:13 +01001686 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001687 goto error;
1688 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001690 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001691 goto error;
1692 }
Radek Krejcie534c132016-11-23 13:32:31 +01001693
Michal Vasko53b7da02018-02-13 15:28:42 +01001694 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001695 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001697 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001698 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001699 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 goto error;
1701 }
Radek Krejcieac35532015-05-31 19:09:15 +02001702
Michal Vasko478c4652016-07-21 12:55:01 +02001703 /* check default value (if not defined, there still could be some restrictions
1704 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001705 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001706 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001707 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001709
Radek Krejcie534c132016-11-23 13:32:31 +01001710 /* finish extensions parsing */
1711 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001712 /* some extensions may be already present from the substatements */
1713 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001714 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001715 tpdf->ext = reallocated;
1716
1717 /* init memory */
1718 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1719
Radek Krejcie534c132016-11-23 13:32:31 +01001720 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001721 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 +01001722 tpdf->ext_size++;
1723 if (rc) {
1724 goto error;
1725 }
1726 }
1727 }
1728
PavolVican92f23622017-12-12 13:35:56 +01001729 for (i = 0; i < tpdf->ext_size; ++i) {
1730 /* set flag, which represent LYEXT_OPT_VALID */
1731 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001732 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001733 break;
1734 }
1735 }
1736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001738
1739error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001741}
1742
Radek Krejcia1a6b762016-11-14 09:53:38 +09001743static int
Radek Krejcie534c132016-11-23 13:32:31 +01001744fill_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 +09001745{
Michal Vasko53b7da02018-02-13 15:28:42 +01001746 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001747 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001748 struct lyxml_elem *child, *node, *next, *next2;
1749 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001750 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001751
Michal Vasko53b7da02018-02-13 15:28:42 +01001752 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001753
Michal Vasko53b7da02018-02-13 15:28:42 +01001754 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001755 goto error;
1756 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001757 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001758
Radek Krejci07d0fb92017-01-13 14:11:05 +01001759 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001760 goto error;
1761 }
1762
Radek Krejcie534c132016-11-23 13:32:31 +01001763 LY_TREE_FOR_SAFE(yin->child, next, node) {
1764 if (strcmp(node->ns->value, LY_NSYIN)) {
1765 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001766 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001767 c_ext++;
1768 } else if (!strcmp(node->name, "argument")) {
1769 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001770 GETVAL(ctx, value, node, "name");
1771 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001772 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001773 goto error;
1774 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001775
Radek Krejcia1a6b762016-11-14 09:53:38 +09001776 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001777 LY_TREE_FOR_SAFE(node->child, next2, child) {
1778 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001779 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001780 if (ly_strequal(value, "true", 0)) {
1781 ext->flags |= LYS_YINELEM;
1782 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001783
Radek Krejci8d6b7422017-02-03 14:42:13 +01001784 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001785 goto error;
1786 }
Radek Krejcie534c132016-11-23 13:32:31 +01001787 } else if (child->ns) {
1788 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001789 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001790 goto error;
1791 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001792 }
1793
Michal Vasko53b7da02018-02-13 15:28:42 +01001794 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001795 } else {
1796 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001797 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001798 goto error;
1799 }
1800 }
1801
1802 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001803 /* some extensions may be already present from the substatements */
1804 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001805 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001806 ext->ext = reallocated;
1807
1808 /* init memory */
1809 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1810
1811 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001812 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001813 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 +01001814 ext->ext_size++;
1815 if (rc) {
1816 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001817 }
1818 }
1819 }
1820
Radek Krejci0a498f82017-01-04 16:24:15 +01001821 /* search for plugin */
1822 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 +09001823
1824 return EXIT_SUCCESS;
1825
1826error:
1827 return EXIT_FAILURE;
1828}
1829
Michal Vasko0d343d12015-08-24 14:57:36 +02001830/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001831static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001832fill_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 +02001833{
Michal Vasko53b7da02018-02-13 15:28:42 +01001834 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001835 const char *value;
1836 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001837 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001838 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001839
Michal Vasko53b7da02018-02-13 15:28:42 +01001840 GETVAL(ctx, value, yin, "name");
1841 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001842 goto error;
1843 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001844 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001845 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001846
Radek Krejci07d0fb92017-01-13 14:11:05 +01001847 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001848 goto error;
1849 }
1850
Radek Krejcie534c132016-11-23 13:32:31 +01001851 LY_TREE_FOR(yin->child, child) {
1852 if (strcmp(child->ns->value, LY_NSYIN)) {
1853 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001854 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001855 c_ext++;
1856 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001857 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001858 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001859 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001860 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001861 goto error;
1862 }
1863 }
1864
Radek Krejcie534c132016-11-23 13:32:31 +01001865 if (c_ftrs) {
1866 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001867 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001868 }
Radek Krejcie534c132016-11-23 13:32:31 +01001869 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001870 /* some extensions may be already present from the substatements */
1871 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001872 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001873 f->ext = reallocated;
1874
1875 /* init memory */
1876 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001877 }
1878
Radek Krejcie534c132016-11-23 13:32:31 +01001879 LY_TREE_FOR_SAFE(yin->child, next, child) {
1880 if (strcmp(child->ns->value, LY_NSYIN)) {
1881 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001882 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 +01001883 f->ext_size++;
1884 if (ret) {
1885 goto error;
1886 }
1887 } else { /* if-feature */
1888 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1889 f->iffeature_size++;
1890 if (ret) {
1891 goto error;
1892 }
1893 }
1894 }
1895
Radek Krejcic79c6b12016-07-26 15:11:49 +02001896 /* check for circular dependencies */
1897 if (f->iffeature_size) {
1898 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1899 goto error;
1900 }
1901 }
1902
Radek Krejci3cf9e222015-06-18 11:37:50 +02001903 return EXIT_SUCCESS;
1904
1905error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001906 return EXIT_FAILURE;
1907}
1908
Michal Vasko0d343d12015-08-24 14:57:36 +02001909/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001910static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001911fill_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 +02001912{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001914
Michal Vasko53b7da02018-02-13 15:28:42 +01001915 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001916 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001917 if (!must->expr) {
1918 goto error;
1919 }
Radek Krejci800af702015-06-02 13:46:01 +02001920
Radek Krejciaa9c5202017-02-15 16:10:14 +01001921 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001922
Michal Vasko77dc5652016-02-15 12:32:42 +01001923error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001924 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001925}
1926
Radek Krejci581ce772015-11-10 17:22:40 +01001927static int
Radek Krejci7417a082017-02-16 11:07:59 +01001928fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1929 struct unres_schema *unres)
1930{
Michal Vasko53b7da02018-02-13 15:28:42 +01001931 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001932 struct lyxml_elem *next, *child;
1933 const char *value;
1934
Michal Vasko53b7da02018-02-13 15:28:42 +01001935 GETVAL(ctx, value, yin, "date");
1936 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001937 goto error;
1938 }
1939 memcpy(rev->date, value, LY_REV_SIZE - 1);
1940
1941 LY_TREE_FOR_SAFE(yin->child, next, child) {
1942 if (!child->ns) {
1943 /* garbage */
1944 continue;
1945 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1946 /* possible extension instance */
1947 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1948 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1949 goto error;
1950 }
1951 } else if (!strcmp(child->name, "description")) {
1952 if (rev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001953 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001954 goto error;
1955 }
1956 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1957 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1958 goto error;
1959 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001960 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001961 if (!rev->dsc) {
1962 goto error;
1963 }
1964 } else if (!strcmp(child->name, "reference")) {
1965 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001966 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001967 goto error;
1968 }
1969 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1970 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1971 goto error;
1972 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001973 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001974 if (!rev->ref) {
1975 goto error;
1976 }
1977 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001978 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001979 goto error;
1980 }
1981 }
1982
1983 return EXIT_SUCCESS;
1984
1985error:
1986 return EXIT_FAILURE;
1987}
1988
1989static int
Michal Vasko88c29542015-11-27 14:57:53 +01001990fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1991 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001992{
Michal Vasko53b7da02018-02-13 15:28:42 +01001993 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02001994 int i, j, ret = EXIT_FAILURE;
1995 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02001996 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001997 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001998
1999 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01002000 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01002001
2002 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002003 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01002004 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002005 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002006 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02002007 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01002008 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01002009 while (isspace(*vaux)) {
2010 vaux++;
2011 }
2012 }
2013 unique->expr_size++;
2014 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002015 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002016
2017 for (i = 0; i < unique->expr_size; i++) {
2018 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02002019 if (vaux) {
2020 c = *vaux;
2021 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01002022 }
2023
2024 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002025 unique->expr[i] = transform_schema2json(module, value);
2026 if (vaux) {
2027 *vaux = c;
2028 }
Radek Krejci581ce772015-11-10 17:22:40 +01002029
2030 /* check that the expression does not repeat */
2031 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002032 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002033 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
2034 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01002035 goto error;
2036 }
2037 }
2038
2039 /* try to resolve leaf */
2040 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002041 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01002042 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02002043 unique_info->list = parent;
2044 unique_info->expr = unique->expr[i];
2045 unique_info->trg_type = &unique->trg_type;
2046 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02002047 goto error;
2048 }
Radek Krejci581ce772015-11-10 17:22:40 +01002049 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002050 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002051 goto error;
2052 }
2053 }
2054
2055 /* move to next token */
2056 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002057 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002058 value++;
2059 }
2060 }
2061
Radek Krejci1a9c3612017-04-24 14:49:43 +02002062 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002063
2064error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002065 free(start);
2066 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002067}
2068
Michal Vasko0d343d12015-08-24 14:57:36 +02002069/* logs directly
2070 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002071 * type: 0 - min, 1 - max
2072 */
2073static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002074deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002075{
2076 const char *value;
2077 char *endptr;
2078 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002079 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002080 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002081
Michal Vaskof7e57d52016-03-07 11:31:09 +01002082 /* del min/max is forbidden */
2083 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002084 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002085 goto error;
2086 }
2087
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002089 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002090 max = &((struct lys_node_leaflist *)target)->max;
2091 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002092 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002093 max = &((struct lys_node_list *)target)->max;
2094 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002095 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002096 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2097 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 goto error;
2099 }
2100
Michal Vasko53b7da02018-02-13 15:28:42 +01002101 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002102 while (isspace(value[0])) {
2103 value++;
2104 }
2105
Radek Krejci0d7b2472016-02-12 11:11:03 +01002106 if (type && !strcmp(value, "unbounded")) {
2107 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002108 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002109 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002110 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002111 /* convert it to uint32_t */
2112 errno = 0;
2113 endptr = NULL;
2114 val = strtoul(value, &endptr, 10);
2115 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002116 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002117 goto error;
2118 }
2119 if (type) {
2120 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002121 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002122 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002123 } else {
2124 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002125 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002126 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002127 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002128 }
2129
2130 if (d->mod == LY_DEVIATE_ADD) {
2131 /* check that there is no current value */
2132 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002133 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2134 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002135 goto error;
2136 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002137 } else if (d->mod == LY_DEVIATE_RPL) {
2138 /* unfortunately, there is no way to check reliably that there
2139 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002140 }
2141
Michal Vaskof7e57d52016-03-07 11:31:09 +01002142 /* add (already checked) and replace */
2143 /* set new value specified in deviation */
2144 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002145
Pavol Vican09adcc32016-08-25 10:51:36 +02002146 /* check min-elements is smaller than max-elements */
2147 if (*max && *min > *max) {
2148 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002149 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2150 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002151 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002152 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2153 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002154 }
2155 goto error;
2156 }
2157
Radek Krejcieb00f512015-07-01 16:44:58 +02002158 return EXIT_SUCCESS;
2159
2160error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002161 return EXIT_FAILURE;
2162}
2163
Michal Vasko0d343d12015-08-24 14:57:36 +02002164/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002165static int
Michal Vasko88c29542015-11-27 14:57:53 +01002166fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2167 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002168{
2169 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002170 struct lyxml_elem *next, *next2, *child, *develem;
2171 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002172 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002173 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002174 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002175 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002176 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002177 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002178 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002179 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002180 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002181 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002182 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002183 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002184 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002185 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002186 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002187 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002188 void *reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002189
Michal Vasko53b7da02018-02-13 15:28:42 +01002190 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002191 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002192 if (!dev->target_name) {
2193 goto error;
2194 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002195
2196 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002197 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2198 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002199 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002200 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002201 goto error;
2202 }
Michal Vasko50576712017-07-28 12:28:33 +02002203 dev_target = set->set.s[0];
2204 ly_set_free(set);
2205
Radek Krejcic4283442016-04-22 09:19:27 +02002206 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002207 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2208 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002209 goto error;
2210 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002211
2212 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002213 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002214 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002215 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002216 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002217 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2218 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002219 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002220 c_ext++;
2221 continue;
2222 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002223 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002224 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002225 goto error;
2226 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002227 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002228 goto error;
2229 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002230 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002231 if (!dev->dsc) {
2232 goto error;
2233 }
2234 } else if (!strcmp(child->name, "reference")) {
2235 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002236 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002237 goto error;
2238 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002239 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002240 goto error;
2241 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002242 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002243 if (!dev->ref) {
2244 goto error;
2245 }
2246 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002247 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002248 c_dev++;
2249
Michal Vasko345da0a2015-12-02 10:35:55 +01002250 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002251 * further processed later
2252 */
2253 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002254
Radek Krejcieb00f512015-07-01 16:44:58 +02002255 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002256 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002257 goto error;
2258 }
2259
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002260 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002261 }
2262
2263 if (c_dev) {
2264 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002265 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002266 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002267 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002268 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002269 }
Radek Krejcie534c132016-11-23 13:32:31 +01002270 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002271 /* some extensions may be already present from the substatements */
2272 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002273 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002274 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002275
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002276 /* init memory */
2277 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2278 }
Radek Krejcie534c132016-11-23 13:32:31 +01002279
2280 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2281 if (strcmp(develem->ns->value, LY_NSYIN)) {
2282 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002283 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 +01002284 dev->ext_size++;
2285 if (rc) {
2286 goto error;
2287 }
2288 continue;
2289 }
2290
2291 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002292 /* init */
2293 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002294 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002295 c_must = 0;
2296 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002297 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002298 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002299
2300 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002301 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002302 if (!strcmp(value, "not-supported")) {
2303 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002304 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002305 * not-supported deviation must be the only deviation of the target
2306 */
2307 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002308 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2309 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 +02002310 goto error;
2311 }
2312
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002313 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002314 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2315 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2316 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002317 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2318 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002319 goto error;
2320 }
2321 }
2322 }
Radek Krejci5b917642015-07-02 09:03:13 +02002323
Michal Vaskoff006c12016-02-17 11:15:19 +01002324 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002325 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002326 lys_node_unlink(dev_target);
Michal Vaskoa1074a52018-01-03 12:18:53 +01002327 if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01002328 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2329 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2330 * path), so we need to remember the augment as an addition */
Michal Vaskoa1074a52018-01-03 12:18:53 +01002331 /* remember uses parent so we can reconnect to it */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002332 dev_target->parent = parent;
2333 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002334 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002335
Radek Krejcieb00f512015-07-01 16:44:58 +02002336 } else if (!strcmp(value, "add")) {
2337 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2338 } else if (!strcmp(value, "replace")) {
2339 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2340 } else if (!strcmp(value, "delete")) {
2341 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2342 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002343 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002344 goto error;
2345 }
2346 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002347 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002348
Michal Vaskoff006c12016-02-17 11:15:19 +01002349 /* store a shallow copy of the original node */
2350 if (!dev->orig_node) {
2351 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002352 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002353 /* just to be safe */
2354 if (tmp_unres.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002355 LOGINT(ctx);
Michal Vaskoff006c12016-02-17 11:15:19 +01002356 goto error;
2357 }
2358 }
2359
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002361 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002362 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002363 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002364 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002365 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002366 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2367 /* extensions */
Michal Vasko53b7da02018-02-13 15:28:42 +01002368 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, d->ext_size, "extensions", "deviate", error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002369 c_ext++;
2370 } else if (d->mod == LY_DEVIATE_NO) {
2371 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002372 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002373 goto error;
2374 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002375 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002376 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002377 goto error;
2378 }
2379
2380 /* for we deviate from RFC 6020 and allow config property even it is/is not
2381 * specified in the target explicitly since config property inherits. So we expect
2382 * that config is specified in every node. But for delete, we check that the value
2383 * is the same as here in deviation
2384 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002385 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002386 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002387 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002388 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002389 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002390 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002391 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002392 goto error;
2393 }
2394
2395 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002396 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002397 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002398 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002399 } else { /* add and replace are the same in this case */
2400 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002401 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002402
2403 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002404 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002405 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002406
Radek Krejci8d6b7422017-02-03 14:42:13 +01002407 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002408 goto error;
2409 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002410 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002411 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 +01002412 goto error;
2413 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002414 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002415 c_dflt++;
2416
2417 /* check target node type */
2418 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002419 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2420 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002421 goto error;
2422 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002423 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2424 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002425 goto error;
2426 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002427 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2428 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002429 goto error;
2430 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002431
Radek Krejcid5a5c282016-08-15 15:38:08 +02002432 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2433 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002434
Radek Krejcieb00f512015-07-01 16:44:58 +02002435 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002436 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002437 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002438 goto error;
2439 }
2440
2441 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002442 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002443 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2444 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002445 goto error;
2446 }
2447
Michal Vasko53b7da02018-02-13 15:28:42 +01002448 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002449 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002450 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002451 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002452 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002453 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002454 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002455 goto error;
2456 }
2457
2458 if (d->mod == LY_DEVIATE_ADD) {
2459 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002460 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002461 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2462 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002463 goto error;
2464 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002465
Radek Krejci841ec082016-04-05 13:05:17 +02002466 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002467 if (d->flags & LYS_MAND_TRUE) {
2468 if (dev_target->nodetype == LYS_CHOICE) {
2469 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002470 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2471 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002472 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2473 goto error;
2474 }
2475 } else if (dev_target->nodetype == LYS_LEAF) {
2476 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002477 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2478 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002479 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2480 goto error;
2481 }
2482 }
Radek Krejci841ec082016-04-05 13:05:17 +02002483 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002484
Michal Vasko21be1b32016-03-07 12:31:34 +01002485 dev_target->flags |= d->flags & LYS_MAND_MASK;
2486 } else if (d->mod == LY_DEVIATE_RPL) {
2487 /* check that there was a value before */
2488 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002489 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2490 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002491 goto error;
2492 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002493
Michal Vasko21be1b32016-03-07 12:31:34 +01002494 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002495 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002496 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002497 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002498 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002499 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002500 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002501
2502 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2503 for (parent = dev_target->parent;
2504 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2505 parent = parent->parent) {
2506 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2507 /* stop also on presence containers */
2508 break;
2509 }
2510 }
2511 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2512 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2513 if (lyp_check_mandatory_choice(parent)) {
2514 goto error;
2515 }
2516 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002517
Radek Krejci8d6b7422017-02-03 14:42:13 +01002518 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002519 goto error;
2520 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002521 } else if (!strcmp(child->name, "min-elements")) {
2522 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002523 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002524 goto error;
2525 }
2526 f_min = 1;
2527
Michal Vasko60f4b452016-02-12 11:02:55 +01002528 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002529 goto error;
2530 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002531 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002532 goto error;
2533 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002534 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002535 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002536 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002537 goto error;
2538 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002539 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002540
Michal Vasko60f4b452016-02-12 11:02:55 +01002541 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002542 goto error;
2543 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002544 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002545 goto error;
2546 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002547 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002548 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002549 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002550 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002551 continue;
2552 } else if (!strcmp(child->name, "type")) {
2553 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002554 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002555 goto error;
2556 }
2557
Michal Vaskof7e57d52016-03-07 11:31:09 +01002558 /* add, del type is forbidden */
2559 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002560 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002561 goto error;
2562 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002563 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002564 goto error;
2565 }
2566
Radek Krejcieb00f512015-07-01 16:44:58 +02002567 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002568 if (dev_target->nodetype == LYS_LEAF) {
2569 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002570 if (((struct lys_node_leaf *)dev_target)->dflt) {
2571 ly_set_add(dflt_check, dev_target, 0);
2572 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002573 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2574 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002575 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2576 ly_set_add(dflt_check, dev_target, 0);
2577 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002578 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002579 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2580 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002581 goto error;
2582 }
2583
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002585 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002586 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002587 /* HACK for unres */
2588 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002589 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002590 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002591 goto error;
2592 }
2593 d->type = t;
2594 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002595 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 +01002596 goto error;
2597 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002598 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002599 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002600 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002601 continue;
2602 } else if (!strcmp(child->name, "units")) {
2603 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002604 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002605 goto error;
2606 }
2607
2608 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002609 if (dev_target->nodetype == LYS_LEAFLIST) {
2610 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2611 } else if (dev_target->nodetype == LYS_LEAF) {
2612 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002613 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002614 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2615 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002616 goto error;
2617 }
2618
2619 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002620 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002621 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002622
2623 /* apply to target */
2624 if (d->mod == LY_DEVIATE_ADD) {
2625 /* check that there is no current value */
2626 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002627 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2628 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002629 goto error;
2630 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002631
Michal Vasko21be1b32016-03-07 12:31:34 +01002632 *stritem = lydict_insert(ctx, value, 0);
2633 } else if (d->mod == LY_DEVIATE_RPL) {
2634 /* check that there was a value before */
2635 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002636 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2637 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002638 goto error;
2639 }
2640
2641 lydict_remove(ctx, *stritem);
2642 *stritem = lydict_insert(ctx, value, 0);
2643 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002644 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002645 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002646 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2647 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002648 goto error;
2649 }
2650 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002651 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002652 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002653
2654 /* remove its extensions */
2655 j = -1;
2656 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2657 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2658 --j;
2659 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002660 }
2661
Radek Krejci8d6b7422017-02-03 14:42:13 +01002662 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002663 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002664 }
2665 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002666 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002667 goto error;
2668 }
2669
Michal Vasko88c29542015-11-27 14:57:53 +01002670 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002671 }
2672
2673 if (c_must) {
2674 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002675 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002676 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002677 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2678 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002679 break;
Radek Krejci76512572015-08-04 09:47:08 +02002680 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002681 trg_must = &((struct lys_node_container *)dev_target)->must;
2682 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002683 break;
Radek Krejci76512572015-08-04 09:47:08 +02002684 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002685 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2686 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002687 break;
Radek Krejci76512572015-08-04 09:47:08 +02002688 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002689 trg_must = &((struct lys_node_list *)dev_target)->must;
2690 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002691 break;
Radek Krejci76512572015-08-04 09:47:08 +02002692 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002693 case LYS_ANYDATA:
2694 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2695 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002696 break;
2697 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002698 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2699 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002700 goto error;
2701 }
2702
Michal Vaskoc04173b2018-03-09 10:43:22 +01002703 dev_target->flags &= ~(LYS_XPCONF_DEP | LYS_XPSTATE_DEP);
Michal Vasko508a50d2016-09-07 14:50:33 +02002704
Radek Krejcieb00f512015-07-01 16:44:58 +02002705 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002706 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002707 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002708 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002709 } else if (d->mod == LY_DEVIATE_ADD) {
2710 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002711 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01002712 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002713 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002714 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002715 d->must_size = c_must;
2716 } else { /* LY_DEVIATE_DEL */
2717 d->must = calloc(c_must, sizeof *d->must);
2718 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002719 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002720 }
2721 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002722 /* replace unique is forbidden */
2723 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002724 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002725 goto error;
2726 }
2727
Radek Krejcieb00f512015-07-01 16:44:58 +02002728 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002729 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002730 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2731 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002732 goto error;
2733 }
2734
Michal Vasko60f4b452016-02-12 11:02:55 +01002735 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002736 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002737 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002738 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002739 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002740 list->unique = d->unique;
2741 d->unique = &list->unique[list->unique_size];
2742 d->unique_size = c_uniq;
2743 } else { /* LY_DEVIATE_DEL */
2744 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002745 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002746 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002747 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002748 if (c_dflt) {
2749 if (d->mod == LY_DEVIATE_ADD) {
2750 /* check that there is no current value */
2751 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2752 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002753 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2754 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002755 goto error;
2756 }
2757
2758 /* check collision with mandatory/min-elements */
2759 if ((dev_target->flags & LYS_MAND_TRUE) ||
2760 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002761 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2762 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002763 "Adding the \"default\" statement is forbidden on %s statement.",
2764 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2765 goto error;
2766 }
2767 } else if (d->mod == LY_DEVIATE_RPL) {
2768 /* check that there was a value before */
2769 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2770 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002771 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2772 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002773 goto error;
2774 }
2775 }
2776
2777 if (dev_target->nodetype == LYS_LEAFLIST) {
2778 /* reallocate default list in the target */
2779 llist = (struct lys_node_leaflist *)dev_target;
2780 if (d->mod == LY_DEVIATE_ADD) {
2781 /* reallocate (enlarge) the unique array of the target */
2782 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002783 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002784 } else if (d->mod == LY_DEVIATE_RPL) {
2785 /* reallocate (replace) the unique array of the target */
2786 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002787 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002788 }
2789 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2790 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002791 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002792 }
2793 }
2794 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002795 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002796 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002797 if (c_ext) {
2798 /* some extensions may be already present from the substatements */
2799 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002800 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002801 d->ext = reallocated;
2802
2803 /* init memory */
2804 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2805 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002806
2807 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002808 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2809 if (strcmp(child->ns->value, LY_NSYIN)) {
2810 /* extension */
2811 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2812 goto error;
2813 }
2814 d->ext_size++;
2815 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002816 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002817 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002818 goto error;
2819 }
2820
2821 /* find must to delete, we are ok with just matching conditions */
2822 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002823 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002824 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002825 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002826 /* ... and maintain the array */
2827 (*trg_must_size)--;
2828 if (i != *trg_must_size) {
2829 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2830 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2831 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2832 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2833 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2834 }
2835 if (!(*trg_must_size)) {
2836 free(*trg_must);
2837 *trg_must = NULL;
2838 } else {
2839 (*trg_must)[*trg_must_size].expr = NULL;
2840 (*trg_must)[*trg_must_size].dsc = NULL;
2841 (*trg_must)[*trg_must_size].ref = NULL;
2842 (*trg_must)[*trg_must_size].eapptag = NULL;
2843 (*trg_must)[*trg_must_size].emsg = NULL;
2844 }
2845
2846 i = -1; /* set match flag */
2847 break;
2848 }
2849 }
2850 d->must_size++;
2851 if (i != -1) {
2852 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002853 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002854 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002855 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002856 goto error;
2857 }
2858 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002859 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002860 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002861 goto error;
2862 }
2863 (*trg_must_size)++;
2864 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002865
2866 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002867 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2868 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002869 goto error;
2870 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002871 } else if (!strcmp(child->name, "unique")) {
2872 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002873 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002874 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002875 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002876 goto error;
2877 }
2878
2879 /* find unique structures to delete */
2880 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002881 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002882 continue;
2883 }
2884
Radek Krejci581ce772015-11-10 17:22:40 +01002885 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002886 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002887 break;
2888 }
2889 }
2890
Radek Krejci581ce772015-11-10 17:22:40 +01002891 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002892 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002893 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002894 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002895 }
2896 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002897 /* ... and maintain the array */
2898 list->unique_size--;
2899 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002900 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2901 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002902 }
2903
2904 if (!list->unique_size) {
2905 free(list->unique);
2906 list->unique = NULL;
2907 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002908 list->unique[list->unique_size].expr_size = 0;
2909 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002910 }
2911
Radek Krejci6bd2c022017-02-01 15:04:49 +01002912 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002913 i = -1; /* set match flag */
2914 break;
2915 }
2916 }
2917
2918 d->unique_size++;
2919 if (i != -1) {
2920 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002921 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2922 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002923 goto error;
2924 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002925
2926 /* remove extensions of this unique instance from the target node */
2927 j = -1;
2928 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 +01002929 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002930 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2931 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002932 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002933 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002934 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002935 }
2936 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002937 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002938 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002939 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002940 list->unique_size++;
2941 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002942 goto error;
2943 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002944 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002945 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002946 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002947 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002948 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002949
2950 if (dev_target->nodetype == LYS_CHOICE) {
2951 choice = (struct lys_node_choice *)dev_target;
2952 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2953 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002954 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002955 goto error;
2956 }
2957 if (d->mod == LY_DEVIATE_DEL) {
2958 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002959 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2960 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002961 goto error;
2962 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002963 choice->dflt = NULL;
2964 /* remove extensions of this default instance from the target node */
2965 j = -1;
2966 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2967 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2968 --j;
2969 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002970 } else { /* add or replace */
2971 choice->dflt = node;
2972 if (!choice->dflt) {
2973 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002974 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002975 goto error;
2976 }
2977 }
2978 } else if (dev_target->nodetype == LYS_LEAF) {
2979 leaf = (struct lys_node_leaf *)dev_target;
2980 if (d->mod == LY_DEVIATE_DEL) {
2981 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002982 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2983 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002984 goto error;
2985 }
2986 /* remove value */
2987 lydict_remove(ctx, leaf->dflt);
2988 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002989 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002990
2991 /* remove extensions of this default instance from the target node */
2992 j = -1;
2993 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2994 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2995 --j;
2996 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002997 } else { /* add (already checked) and replace */
2998 /* remove value */
2999 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01003000 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003001
3002 /* set new value */
3003 leaf->dflt = lydict_insert(ctx, value, u);
3004
Radek Krejcibd117f02016-11-04 16:28:08 +01003005 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02003006 ly_set_add(dflt_check, dev_target, 0);
3007 }
3008 } else { /* LYS_LEAFLIST */
3009 llist = (struct lys_node_leaflist *)dev_target;
3010 if (d->mod == LY_DEVIATE_DEL) {
3011 /* find and remove the value in target list */
3012 for (i = 0; i < llist->dflt_size; i++) {
3013 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
3014 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01003015 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003016 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003017
3018 /* remove extensions of this default instance from the target node */
3019 j = -1;
3020 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 +01003021 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003022 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3023 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003024 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003025 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003026 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003027 }
3028 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003029 break;
3030 }
3031 }
3032 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003033 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3034 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 +02003035 goto error;
3036 }
3037 } else {
3038 /* add or replace, anyway we place items into the deviate's list
3039 which propagates to the target */
3040 /* we just want to check that the value isn't already in the list */
3041 for (i = 0; i < llist->dflt_size; i++) {
3042 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003043 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3044 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003045 goto error;
3046 }
3047 }
3048 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003049 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003050
3051 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3052 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003053 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003054 }
3055 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003056 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003057 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003058
3059 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3060 /* consolidate the final list in the target after removing items from it */
3061 llist = (struct lys_node_leaflist *)dev_target;
3062 for (i = j = 0; j < llist->dflt_size; j++) {
3063 llist->dflt[i] = llist->dflt[j];
3064 if (llist->dflt[i]) {
3065 i++;
3066 }
3067 }
3068 llist->dflt_size = i + 1;
3069 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003070 }
3071
Michal Vasko43a1feb2016-03-07 12:03:02 +01003072 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003073 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003074 for (u = 0; u < dflt_check->number; ++u) {
3075 value = NULL;
3076 rc = EXIT_SUCCESS;
3077 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3078 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3079 value = leaf->dflt;
3080 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3081 } else { /* LYS_LEAFLIST */
3082 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3083 for (j = 0; j < llist->dflt_size; j++) {
3084 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3085 (struct lys_node *)(&llist->dflt[j]));
3086 if (rc == -1) {
3087 value = llist->dflt[j];
3088 break;
3089 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003090 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003091
Michal Vasko15a43372017-09-25 14:12:42 +02003092 }
3093 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003094 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3095 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003096 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3097 dev->target_name);
3098 goto error;
3099 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003100 }
3101 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003102
Radek Krejci27fe55e2016-09-13 17:13:35 +02003103 /* mark all the affected modules as deviated and implemented */
3104 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3105 mod = lys_node_module(parent);
3106 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003107 mod->deviated = 1; /* main module */
3108 parent->module->deviated = 1; /* possible submodule */
Michal Vasko0f437062018-06-08 15:52:39 +02003109 if (!mod->implemented) {
3110 mod->implemented = 1;
3111 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
3112 goto error;
3113 }
Radek Krejci2bb5be72017-02-27 13:07:25 +01003114 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003115 }
3116 }
3117
Radek Krejcid5a5c282016-08-15 15:38:08 +02003118 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003119 return EXIT_SUCCESS;
3120
3121error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003122 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003123 return EXIT_FAILURE;
3124}
3125
Michal Vasko0d343d12015-08-24 14:57:36 +02003126/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003127static int
Radek Krejcib8048692015-08-05 13:36:34 +02003128fill_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 +01003129 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003130{
Michal Vasko53b7da02018-02-13 15:28:42 +01003131 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003133 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003134 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003135 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003136 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003137
Michal Vasko591e0b22015-08-13 13:53:43 +02003138 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003139 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003140 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003141 if (!aug->target_name) {
3142 goto error;
3143 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003144 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003145
Radek Krejci07d0fb92017-01-13 14:11:05 +01003146 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003147 goto error;
3148 }
3149
Radek Krejcie534c132016-11-23 13:32:31 +01003150 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3151 if (strcmp(sub->ns->value, LY_NSYIN)) {
3152 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003153 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003154 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003155 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003156 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003157 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003158 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003159 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003160 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003161 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003162 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003163 goto error;
3164 }
3165
Radek Krejci5323b492017-01-16 15:40:11 +01003166 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003167 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003168 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003169 goto error;
3170 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003171 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003172 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003173
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003174 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003175 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003176 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003177 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003178 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003179 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003180 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003181 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003182 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003183 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003184 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003185 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003186 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003187 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003188 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003189 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003190 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003191 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003192 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003193 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003194 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003195 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003196 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003197 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003198 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003199 goto error;
3200 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003201
Radek Krejci1d82ef62015-08-07 14:44:40 +02003202 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003203 goto error;
3204 }
3205
Radek Krejci1d82ef62015-08-07 14:44:40 +02003206 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003207 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003208 }
3209
Radek Krejcie534c132016-11-23 13:32:31 +01003210 if (c_ftrs) {
3211 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003212 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003213 }
Radek Krejcie534c132016-11-23 13:32:31 +01003214 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003215 /* some extensions may be already present from the substatements */
3216 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003217 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003218 aug->ext = reallocated;
3219
3220 /* init memory */
3221 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003222 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003223
Radek Krejcie534c132016-11-23 13:32:31 +01003224 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3225 if (strcmp(sub->ns->value, LY_NSYIN)) {
3226 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003227 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 +01003228 aug->ext_size++;
3229 if (ret) {
3230 goto error;
3231 }
3232 } else if (!strcmp(sub->name, "if-feature")) {
3233 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003234 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003235 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003236 goto error;
3237 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003238 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003239 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003240 }
3241
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003242 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003243 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003244 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003245 * when the uses does and cannot be resolved now for sure
3246 * (the grouping was not yet copied into uses).
3247 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003248 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003249 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003250 goto error;
3251 }
Michal Vasko49291b32015-08-06 09:49:41 +02003252 }
Radek Krejci106efc02015-06-10 14:36:27 +02003253
Michal Vasko508a50d2016-09-07 14:50:33 +02003254 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003255 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003256 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003257 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003258 goto error;
3259 }
3260 } else {
3261 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3262 goto error;
3263 }
3264 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003265 }
3266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003268
3269error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003271}
3272
Michal Vasko0d343d12015-08-24 14:57:36 +02003273/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003275fill_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 +02003276{
Michal Vasko53b7da02018-02-13 15:28:42 +01003277 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003278 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 struct lyxml_elem *sub, *next;
3280 const char *value;
3281 char *endptr;
3282 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003283 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 int r;
3285 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003286 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003287
Radek Krejci363bd4a2016-07-29 14:30:20 +02003288 assert(uses);
3289 module = uses->module; /* shorthand */
3290
Michal Vasko53b7da02018-02-13 15:28:42 +01003291 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003292 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003293 if (!rfn->target_name) {
3294 goto error;
3295 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003298 if (!sub->ns) {
3299 /* garbage */
3300 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003301 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003302 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003303 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003304 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003305
Radek Krejci411b1bf2017-01-23 16:40:05 +01003306 } else if (!strcmp(sub->name, "description")) {
3307 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003308 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003309 goto error;
3310 }
3311
Radek Krejci8d6b7422017-02-03 14:42:13 +01003312 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003313 goto error;
3314 }
3315
Michal Vasko53b7da02018-02-13 15:28:42 +01003316 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003317 if (!rfn->dsc) {
3318 goto error;
3319 }
3320 } else if (!strcmp(sub->name, "reference")) {
3321 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003322 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003323 goto error;
3324 }
3325
Radek Krejci8d6b7422017-02-03 14:42:13 +01003326 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003327 goto error;
3328 }
3329
Michal Vasko53b7da02018-02-13 15:28:42 +01003330 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003331 if (!rfn->ref) {
3332 goto error;
3333 }
3334 } else if (!strcmp(sub->name, "config")) {
3335 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003336 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003337 goto error;
3338 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003339 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003340 if (!strcmp(value, "false")) {
3341 rfn->flags |= LYS_CONFIG_R;
3342 } else if (!strcmp(value, "true")) {
3343 rfn->flags |= LYS_CONFIG_W;
3344 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003345 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003346 goto error;
3347 }
3348 rfn->flags |= LYS_CONFIG_SET;
3349
Radek Krejci8d6b7422017-02-03 14:42:13 +01003350 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003351 goto error;
3352 }
Radek Krejcie534c132016-11-23 13:32:31 +01003353 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003354 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 /* check possibility of statements combination */
3357 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003358 if (c_dflt) {
3359 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003360 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003361 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003362 goto error;
3363 }
Radek Krejci200bf712016-08-16 17:11:04 +02003364 rfn->target_type &= LYS_LEAFLIST;
3365 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003366 if (module->version < 2) {
3367 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3368 } else {
3369 /* YANG 1.1 */
3370 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3371 }
Radek Krejci200bf712016-08-16 17:11:04 +02003372 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003374 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3375 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 goto error;
3377 }
3378 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003379 if (module->version < 2) {
3380 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3381 } else {
3382 /* YANG 1.1 */
3383 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3384 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003386
Michal Vasko53b7da02018-02-13 15:28:42 +01003387 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003388 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 +01003389 goto error;
3390 }
Radek Krejci200bf712016-08-16 17:11:04 +02003391 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003392 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 } else if (!strcmp(sub->name, "mandatory")) {
3394 /* leaf, choice or anyxml */
3395 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003396 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003397 goto error;
3398 }
3399 /* just checking the flags in leaf is not sufficient, we would allow
3400 * multiple mandatory statements with the "false" value
3401 */
3402 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 /* check possibility of statements combination */
3405 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003406 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003408 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3409 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 goto error;
3411 }
3412 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003413 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003415
Michal Vasko53b7da02018-02-13 15:28:42 +01003416 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003418 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003420 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003422 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 goto error;
3424 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003425 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003426 goto error;
3427 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 } else if (!strcmp(sub->name, "min-elements")) {
3429 /* list or leaf-list */
3430 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003431 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 goto error;
3433 }
3434 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 /* check possibility of statements combination */
3437 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003438 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003440 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3441 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 goto error;
3443 }
3444 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003445 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003447
Michal Vasko53b7da02018-02-13 15:28:42 +01003448 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 while (isspace(value[0])) {
3450 value++;
3451 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 /* convert it to uint32_t */
3454 errno = 0;
3455 endptr = NULL;
3456 val = strtoul(value, &endptr, 10);
3457 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003458 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 goto error;
3460 }
3461 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003462 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003463
Radek Krejci8d6b7422017-02-03 14:42:13 +01003464 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003465 goto error;
3466 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 } else if (!strcmp(sub->name, "max-elements")) {
3468 /* list or leaf-list */
3469 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003470 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 goto error;
3472 }
3473 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 /* check possibility of statements combination */
3476 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003477 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003479 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3480 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 goto error;
3482 }
3483 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003484 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003486
Michal Vasko53b7da02018-02-13 15:28:42 +01003487 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 while (isspace(value[0])) {
3489 value++;
3490 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003491
Radek Krejci0d7b2472016-02-12 11:11:03 +01003492 if (!strcmp(value, "unbounded")) {
3493 rfn->mod.list.max = 0;
3494 } else {
3495 /* convert it to uint32_t */
3496 errno = 0;
3497 endptr = NULL;
3498 val = strtoul(value, &endptr, 10);
3499 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003500 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003501 goto error;
3502 }
3503 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003505 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003506
Radek Krejci8d6b7422017-02-03 14:42:13 +01003507 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003508 goto error;
3509 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 } else if (!strcmp(sub->name, "presence")) {
3511 /* container */
3512 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003513 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 goto error;
3515 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003516
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 /* check possibility of statements combination */
3518 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003519 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003521 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3522 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003523 goto error;
3524 }
3525 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003526 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003527 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003528
Michal Vasko53b7da02018-02-13 15:28:42 +01003529 GETVAL(ctx, value, sub, "value");
3530 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003531
Radek Krejci8d6b7422017-02-03 14:42:13 +01003532 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003533 goto error;
3534 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003536 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 /* check possibility of statements combination */
3538 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003539 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003541 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3542 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 goto error;
3544 }
3545 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003546 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003548
Michal Vasko53b7da02018-02-13 15:28:42 +01003549 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003551 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003552
Radek Krejci363bd4a2016-07-29 14:30:20 +02003553 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3554 /* leaf, leaf-list, list, container or anyxml */
3555 /* check possibility of statements combination */
3556 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003557 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003558 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003559 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3560 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003561 goto error;
3562 }
3563 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003564 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003565 }
3566
Michal Vasko53b7da02018-02-13 15:28:42 +01003567 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003568 c_ftrs++;
3569 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003571 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 goto error;
3573 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003574
Michal Vasko53b7da02018-02-13 15:28:42 +01003575 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003576 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 /* process nodes with cardinality of 0..n */
3579 if (c_must) {
3580 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003581 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003583 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003584 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003585 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 }
Radek Krejci200bf712016-08-16 17:11:04 +02003587 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003588 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003589 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003590 }
Radek Krejcie534c132016-11-23 13:32:31 +01003591 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003592 /* some extensions may be already present from the substatements */
3593 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003594 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003595 rfn->ext = reallocated;
3596
3597 /* init memory */
3598 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003599 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003600
Radek Krejcie534c132016-11-23 13:32:31 +01003601 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3602 if (strcmp(sub->ns->value, LY_NSYIN)) {
3603 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003604 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 +01003605 rfn->ext_size++;
3606 if (r) {
3607 goto error;
3608 }
3609 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003610 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003611 rfn->iffeature_size++;
3612 if (r) {
3613 goto error;
3614 }
Radek Krejci200bf712016-08-16 17:11:04 +02003615 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003616 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003617 rfn->must_size++;
3618 if (r) {
3619 goto error;
3620 }
Radek Krejci200bf712016-08-16 17:11:04 +02003621 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003622 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003623
3624 /* check for duplicity */
3625 for (r = 0; r < rfn->dflt_size; r++) {
3626 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003627 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3628 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003629 goto error;
3630 }
3631 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003632 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003633 }
3634 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003637
3638error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003640}
3641
Michal Vasko0d343d12015-08-24 14:57:36 +02003642/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643static int
Radek Krejcie534c132016-11-23 13:32:31 +01003644fill_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 +02003645{
Michal Vasko53b7da02018-02-13 15:28:42 +01003646 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003647 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003648 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003649 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003650 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003651
Radek Krejcie534c132016-11-23 13:32:31 +01003652 /* init */
3653 memset(&exts, 0, sizeof exts);
3654
3655 LY_TREE_FOR_SAFE(yin->child, next, child) {
3656 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003657 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003658 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003659 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3660 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003661 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003662 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003663 lyxml_unlink_elem(ctx, child, 2);
3664 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003665 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003666 GETVAL(ctx, value, child, "value");
3667 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 goto error;
3669 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003670 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003671
Radek Krejci8d6b7422017-02-03 14:42:13 +01003672 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003673 goto error;
3674 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 } else if (!strcmp(child->name, "revision-date")) {
3676 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003677 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003678 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003680 GETVAL(ctx, value, child, "date");
3681 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 goto error;
3683 }
3684 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003685
Radek Krejci8d6b7422017-02-03 14:42:13 +01003686 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003687 goto error;
3688 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003689 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003690 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003691 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003692 goto error;
3693 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003694 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003695 goto error;
3696 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003697 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003698 if (!imp->dsc) {
3699 goto error;
3700 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003701 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003702 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003703 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003704 goto error;
3705 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003706 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003707 goto error;
3708 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003709 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003710 if (!imp->ref) {
3711 goto error;
3712 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003714 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 goto error;
3716 }
3717 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003719 /* check mandatory information */
3720 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003721 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 goto error;
3723 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003724
Radek Krejcie534c132016-11-23 13:32:31 +01003725 /* process extensions */
3726 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003727 /* some extensions may be already present from the substatements */
3728 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003729 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003730 imp->ext = reallocated;
3731
3732 /* init memory */
3733 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3734
Radek Krejcie534c132016-11-23 13:32:31 +01003735 LY_TREE_FOR_SAFE(exts.child, next, child) {
3736 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003737 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 +01003738 imp->ext_size++;
3739 if (r) {
3740 goto error;
3741 }
3742 }
3743 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003744
Michal Vasko53b7da02018-02-13 15:28:42 +01003745 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003746 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003747
3748error:
Radek Krejcie534c132016-11-23 13:32:31 +01003749 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003750 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003751 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003753}
3754
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003755/* logs directly
3756 * returns:
3757 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003758 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003759 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003761fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3762 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003763{
Michal Vasko53b7da02018-02-13 15:28:42 +01003764 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003765 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003767 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003768 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003769
Radek Krejcie534c132016-11-23 13:32:31 +01003770 /* init */
3771 memset(&exts, 0, sizeof exts);
3772
3773 LY_TREE_FOR_SAFE(yin->child, next, child) {
3774 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003775 /* garbage */
3776 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003777 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3778 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003779 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003780 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003781 lyxml_unlink_elem(ctx, child, 2);
3782 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003783 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003785 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 goto error;
3787 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003788 GETVAL(ctx, value, child, "date");
3789 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 goto error;
3791 }
3792 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003793
Radek Krejci8d6b7422017-02-03 14:42:13 +01003794 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003795 goto error;
3796 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003797 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003798 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003799 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003800 goto error;
3801 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003802 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003803 goto error;
3804 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003805 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003806 if (!inc->dsc) {
3807 goto error;
3808 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003809 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003810 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003811 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003812 goto error;
3813 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003814 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003815 goto error;
3816 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003817 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003818 if (!inc->ref) {
3819 goto error;
3820 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003822 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003823 goto error;
3824 }
3825 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003826
Radek Krejcie534c132016-11-23 13:32:31 +01003827 /* process extensions */
3828 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003829 /* some extensions may be already present from the substatements */
3830 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003831 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003832 inc->ext = reallocated;
3833
3834 /* init memory */
3835 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3836
Radek Krejcie534c132016-11-23 13:32:31 +01003837 LY_TREE_FOR_SAFE(exts.child, next, child) {
3838 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003839 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 +01003840 inc->ext_size++;
3841 if (r) {
3842 goto error;
3843 }
3844 }
3845 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003846
Michal Vasko53b7da02018-02-13 15:28:42 +01003847 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003848 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003849
3850error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003851 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003852}
3853
Michal Vasko0d343d12015-08-24 14:57:36 +02003854/* logs directly
3855 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003856 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003857 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003858 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003859 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003860static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003861read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3862 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003863{
Radek Krejcie4dce292017-10-30 11:16:47 +01003864 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 const char *value;
3866 struct lyxml_elem *sub, *next;
3867 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003868 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003871 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003875 GETVAL(ctx, value, xmlnode, "name");
3876 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 goto error;
3878 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003879 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 /* process local parameters */
3883 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003884 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003885 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003886 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003887 continue;
3888 }
3889 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003890 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003891 continue;
3892 }
3893
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003894 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003895 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003896 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 goto error;
3898 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003899
Radek Krejci8d6b7422017-02-03 14:42:13 +01003900 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003901 goto error;
3902 }
3903
Radek Krejci1d82ef62015-08-07 14:44:40 +02003904 node->dsc = read_yin_subnode(ctx, sub, "text");
3905 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003906 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 }
3908 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003909 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003910 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 goto error;
3912 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003913
Radek Krejci8d6b7422017-02-03 14:42:13 +01003914 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003915 goto error;
3916 }
3917
Radek Krejci1d82ef62015-08-07 14:44:40 +02003918 node->ref = read_yin_subnode(ctx, sub, "text");
3919 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003920 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 }
3922 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003923 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003924 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 goto error;
3926 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003927 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003929 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003931 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003933 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003935 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003936 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003937 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003938
Radek Krejci8d6b7422017-02-03 14:42:13 +01003939 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003940 goto error;
3941 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003942 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3943 if (opt & OPT_CFG_PARSE) {
3944 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003945 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003946 goto error;
3947 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003948 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003949 if (!strcmp(value, "false")) {
3950 node->flags |= LYS_CONFIG_R;
3951 } else if (!strcmp(value, "true")) {
3952 node->flags |= LYS_CONFIG_W;
3953 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003954 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003955 goto error;
3956 }
3957 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003958
Radek Krejci8d6b7422017-02-03 14:42:13 +01003959 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003960 goto error;
3961 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003964 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 continue;
3966 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003967 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969
Michal Vaskoe022a562016-09-27 14:24:15 +02003970 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003972 if (parent) {
3973 node->flags |= parent->flags & LYS_CONFIG_MASK;
3974 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003976 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 }
3978 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003979
Radek Krejci2cc25322017-09-06 16:32:02 +02003980 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
3981 /* status is not inherited by specification, but it not make sense to have
3982 * current in deprecated or deprecated in obsolete, so we print warning
3983 * and fix the schema by inheriting */
3984 if (!(node->flags & (LYS_STATUS_MASK))) {
3985 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01003986 if (stmt_type == LYEXT_PAR_NODE) {
3987 p = node->parent;
3988 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01003989 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01003990 node->parent = p;
3991 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01003992 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01003993 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003994 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
3995 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02003996 free(str);
3997 node->flags |= parent->flags & LYS_STATUS_MASK;
3998 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
3999 /* invalid combination of statuses */
4000 switch (node->flags & LYS_STATUS_MASK) {
4001 case 0:
4002 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01004003 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004004 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
4005 break;
4006 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01004007 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004008 "obsolete", parent->name);
4009 break;
4010 }
4011 goto error;
4012 }
4013 }
4014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004016
4017error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004018 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004019}
4020
Michal Vasko0d343d12015-08-24 14:57:36 +02004021/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004022static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004023read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004024{
Michal Vasko53b7da02018-02-13 15:28:42 +01004025 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004026 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004027 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004028 const char *value;
4029
4030 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004031 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004032
Michal Vasko53b7da02018-02-13 15:28:42 +01004033 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004034 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004035 if (!retval->cond) {
4036 goto error;
4037 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004038
Radek Krejci5323b492017-01-16 15:40:11 +01004039 LY_TREE_FOR_SAFE(yin->child, next, child) {
4040 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004041 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004042 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004043 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4044 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004045 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004046 goto error;
4047 }
4048 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004049 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004050 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004051 goto error;
4052 }
Radek Krejci5323b492017-01-16 15:40:11 +01004053
Radek Krejci8d6b7422017-02-03 14:42:13 +01004054 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004055 goto error;
4056 }
4057
Michal Vasko53b7da02018-02-13 15:28:42 +01004058 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004059 if (!retval->dsc) {
4060 goto error;
4061 }
4062 } else if (!strcmp(child->name, "reference")) {
4063 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004064 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004065 goto error;
4066 }
Radek Krejci5323b492017-01-16 15:40:11 +01004067
Radek Krejci8d6b7422017-02-03 14:42:13 +01004068 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004069 goto error;
4070 }
4071
Michal Vasko53b7da02018-02-13 15:28:42 +01004072 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004073 if (!retval->ref) {
4074 goto error;
4075 }
4076 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004077 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004078 goto error;
4079 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004080 }
4081
4082 return retval;
4083
4084error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004085 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004086 return NULL;
4087}
4088
Michal Vasko0d343d12015-08-24 14:57:36 +02004089/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004090static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004091read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004092 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004093{
Michal Vasko53b7da02018-02-13 15:28:42 +01004094 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004095 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004096 struct lys_node_case *cs;
4097 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004098 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004099 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004100
Radek Krejcie867c852015-08-27 09:52:34 +02004101 /* init */
4102 memset(&root, 0, sizeof root);
4103
Radek Krejci1d82ef62015-08-07 14:44:40 +02004104 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004105 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004106 cs->nodetype = LYS_CASE;
4107 cs->prev = (struct lys_node *)cs;
4108 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004109
Radek Krejci07d0fb92017-01-13 14:11:05 +01004110 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004111 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004112 goto error;
4113 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004114
Michal Vasko3e3228d2017-02-24 14:55:32 +01004115 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004116
Michal Vasko3a0043f2015-08-12 12:11:30 +02004117 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004118 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004119 goto error;
4120 }
4121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004122 /* process choice's specific children */
4123 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004124 if (strcmp(sub->ns->value, LY_NSYIN)) {
4125 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004126 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004127 c_ext++;
4128 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004129 !strcmp(sub->name, "leaf-list") ||
4130 !strcmp(sub->name, "leaf") ||
4131 !strcmp(sub->name, "list") ||
4132 !strcmp(sub->name, "uses") ||
4133 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004134 !strcmp(sub->name, "anyxml") ||
4135 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004136
Michal Vasko53b7da02018-02-13 15:28:42 +01004137 lyxml_unlink_elem(ctx, sub, 2);
4138 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004139 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004140 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004141 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004142 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004143 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004144 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004145 goto error;
4146 }
4147
Radek Krejci5323b492017-01-16 15:40:11 +01004148 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004149 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004150 goto error;
4151 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004152
Michal Vasko53b7da02018-02-13 15:28:42 +01004153 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004155 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004156 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004158 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004159
Radek Krejci3cf9e222015-06-18 11:37:50 +02004160 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004161 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004162 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004163 }
Radek Krejcie534c132016-11-23 13:32:31 +01004164 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004165 /* some extensions may be already present from the substatements */
4166 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004167 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004168 retval->ext = reallocated;
4169
4170 /* init memory */
4171 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 }
Radek Krejci21c81652017-01-23 10:42:55 +01004173
Radek Krejcie534c132016-11-23 13:32:31 +01004174 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4175 if (strcmp(sub->ns->value, LY_NSYIN)) {
4176 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004177 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 +01004178 retval->ext_size++;
4179 if (ret) {
4180 goto error;
4181 }
4182 } else {
4183 /* if-feature */
4184 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4185 cs->iffeature_size++;
4186 if (ret) {
4187 goto error;
4188 }
4189 }
4190 }
Radek Krejcib388c152015-06-04 17:03:03 +02004191
Michal Vasko29fc0182015-08-24 15:02:39 +02004192 /* last part - process data nodes */
4193 LY_TREE_FOR_SAFE(root.child, next, sub) {
4194 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004195 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004196 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004197 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004198 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004199 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004200 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004201 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004202 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004203 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004204 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004205 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004206 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004207 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004208 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004209 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004210 }
4211 if (!node) {
4212 goto error;
4213 }
4214
Michal Vasko53b7da02018-02-13 15:28:42 +01004215 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004216 }
4217
Michal Vasko508a50d2016-09-07 14:50:33 +02004218 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004219 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004220 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004221 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004222 goto error;
4223 }
4224 } else {
4225 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4226 goto error;
4227 }
4228 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004229 }
4230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004231 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004232
4233error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004234 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004235 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004236 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004237 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004239 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004240}
4241
Michal Vasko0d343d12015-08-24 14:57:36 +02004242/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004243static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004244read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004245 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004246{
Radek Krejci629cdef2016-06-06 15:06:36 +02004247 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004249 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004250 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004251 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004252 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004253 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004256 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004257
Radek Krejci76512572015-08-04 09:47:08 +02004258 choice->nodetype = LYS_CHOICE;
4259 choice->prev = (struct lys_node *)choice;
4260 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004261
Radek Krejci07d0fb92017-01-13 14:11:05 +01004262 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004263 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4264 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4265 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004266 goto error;
4267 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004268
Michal Vasko3e3228d2017-02-24 14:55:32 +01004269 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004270
Michal Vasko3a0043f2015-08-12 12:11:30 +02004271 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004272 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004273 goto error;
4274 }
4275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 /* process choice's specific children */
4277 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004278 if (strcmp(sub->ns->value, LY_NSYIN)) {
4279 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004280 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004281 c_ext++;
4282 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004283 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004284 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004285 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 goto error;
4287 }
4288 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004289 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004290 goto error;
4291 }
4292 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004293 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004294 goto error;
4295 }
4296 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004297 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 goto error;
4299 }
4300 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004301 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 goto error;
4303 }
4304 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004305 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004306 goto error;
4307 }
4308 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004309 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004310 goto error;
4311 }
4312 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004313 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004314 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004315 goto error;
4316 }
Radek Krejci21c81652017-01-23 10:42:55 +01004317
Radek Krejci8d6b7422017-02-03 14:42:13 +01004318 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004319 goto error;
4320 }
4321
Radek Krejci629cdef2016-06-06 15:06:36 +02004322 dflt = sub;
4323 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004324 continue;
4325 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004327 } else if (!strcmp(sub->name, "mandatory")) {
4328 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004329 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 goto error;
4331 }
4332 /* just checking the flags in leaf is not sufficient, we would allow
4333 * multiple mandatory statements with the "false" value
4334 */
4335 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004336
Michal Vasko53b7da02018-02-13 15:28:42 +01004337 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004338 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004339 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004340 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004341 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004342 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004343 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 goto error;
4345 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004346
Radek Krejci8d6b7422017-02-03 14:42:13 +01004347 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004348 goto error;
4349 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004350 } else if (!strcmp(sub->name, "when")) {
4351 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004352 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004353 goto error;
4354 }
4355
Radek Krejci5323b492017-01-16 15:40:11 +01004356 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004357 if (!choice->when) {
4358 goto error;
4359 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004360 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004361 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004362 c_ftrs++;
4363
Michal Vasko345da0a2015-12-02 10:35:55 +01004364 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004365 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004366 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004367 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004368 goto error;
4369 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004371 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004372 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004374
Radek Krejci1d82ef62015-08-07 14:44:40 +02004375 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004376 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004377 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004378
Radek Krejci3cf9e222015-06-18 11:37:50 +02004379 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004380 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004381 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004382 }
Radek Krejcie534c132016-11-23 13:32:31 +01004383 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004384 /* some extensions may be already present from the substatements */
4385 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004386 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004387 retval->ext = reallocated;
4388
4389 /* init memory */
4390 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004391 }
4392
Radek Krejcie534c132016-11-23 13:32:31 +01004393 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4394 if (strcmp(sub->ns->value, LY_NSYIN)) {
4395 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004396 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 +01004397 retval->ext_size++;
4398 if (ret) {
4399 goto error;
4400 }
4401 } else {
4402 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4403 choice->iffeature_size++;
4404 if (ret) {
4405 goto error;
4406 }
4407 }
4408 }
4409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004411 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004412 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4413 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004414 goto error;
4415 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004417 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004418 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004419 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004420 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004421 goto error;
4422 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004423 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004424 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004425
Michal Vasko508a50d2016-09-07 14:50:33 +02004426 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004427 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004428 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004429 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004430 goto error;
4431 }
4432 } else {
4433 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4434 goto error;
4435 }
4436 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004437 }
4438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004439 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004440
4441error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004442 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004443 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004445}
4446
Michal Vasko0d343d12015-08-24 14:57:36 +02004447/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004448static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004449read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004450 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004451{
Michal Vasko53b7da02018-02-13 15:28:42 +01004452 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004453 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004454 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004455 struct lyxml_elem *sub, *next;
4456 const char *value;
4457 int r;
4458 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004459 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004460 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004462 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004463 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004464
Radek Krejcibf2abff2016-08-23 15:51:52 +02004465 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004466 anyxml->prev = (struct lys_node *)anyxml;
4467 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004468
Radek Krejci07d0fb92017-01-13 14:11:05 +01004469 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004470 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004471 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004472 goto error;
4473 }
Radek Krejci863c2852015-06-03 15:47:11 +02004474
Michal Vasko3e3228d2017-02-24 14:55:32 +01004475 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004476
Radek Krejcic189a952016-07-11 15:27:07 +02004477 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004478 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004479 goto error;
4480 }
4481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004482 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004483 if (strcmp(sub->ns->value, LY_NSYIN)) {
4484 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004485 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004486 c_ext++;
4487 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004489 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004490 goto error;
4491 }
4492 /* just checking the flags in leaf is not sufficient, we would allow
4493 * multiple mandatory statements with the "false" value
4494 */
4495 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004496
Michal Vasko53b7da02018-02-13 15:28:42 +01004497 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004498 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004499 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004500 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004501 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004502 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004503 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 goto error;
4505 }
4506 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004507
Radek Krejci8d6b7422017-02-03 14:42:13 +01004508 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004509 goto error;
4510 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004511 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004512 } else if (!strcmp(sub->name, "when")) {
4513 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004514 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004515 goto error;
4516 }
4517
Radek Krejci5323b492017-01-16 15:40:11 +01004518 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004519 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004520 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004521 goto error;
4522 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004523 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004525 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004527 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004528 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004529 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004532 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 }
4535 }
Radek Krejci863c2852015-06-03 15:47:11 +02004536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 /* middle part - process nodes with cardinality of 0..n */
4538 if (c_must) {
4539 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004540 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004541 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004542 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004543 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004544 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004545 }
Radek Krejcie534c132016-11-23 13:32:31 +01004546 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004547 /* some extensions may be already present from the substatements */
4548 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004549 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004550 retval->ext = reallocated;
4551
4552 /* init memory */
4553 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004554 }
Radek Krejci863c2852015-06-03 15:47:11 +02004555
Radek Krejcie534c132016-11-23 13:32:31 +01004556 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4557 if (strcmp(sub->ns->value, LY_NSYIN)) {
4558 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004559 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004560 retval->ext_size++;
4561 if (r) {
4562 goto error;
4563 }
4564 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004565 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004566 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 if (r) {
4568 goto error;
4569 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004570 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004571 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004572 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004573 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004574 goto error;
4575 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 }
Radek Krejci863c2852015-06-03 15:47:11 +02004578
Michal Vasko508a50d2016-09-07 14:50:33 +02004579 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004580 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004581 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004582 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004583 goto error;
4584 }
4585 } else {
4586 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4587 goto error;
4588 }
4589 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004590 }
4591
PavolVican92f23622017-12-12 13:35:56 +01004592 for (r = 0; r < retval->ext_size; ++r) {
4593 /* set flag, which represent LYEXT_OPT_VALID */
4594 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004595 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004596 break;
4597 }
4598 }
4599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004601
4602error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004603 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004604 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004605}
4606
Michal Vasko0d343d12015-08-24 14:57:36 +02004607/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004608static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004609read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004610 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004611{
Michal Vasko53b7da02018-02-13 15:28:42 +01004612 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004613 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004614 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 struct lyxml_elem *sub, *next;
4616 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004617 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004618 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004619 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004622 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004623
Radek Krejci76512572015-08-04 09:47:08 +02004624 leaf->nodetype = LYS_LEAF;
4625 leaf->prev = (struct lys_node *)leaf;
4626 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004627
Radek Krejci07d0fb92017-01-13 14:11:05 +01004628 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004629 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4630 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4631 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 goto error;
4633 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004634
Michal Vasko3e3228d2017-02-24 14:55:32 +01004635 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004636
Radek Krejcic189a952016-07-11 15:27:07 +02004637 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004638 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004639 goto error;
4640 }
4641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004643 if (strcmp(sub->ns->value, LY_NSYIN)) {
4644 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004645 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004646 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004647 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004648 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004649 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004650 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 goto error;
4652 }
Michal Vasko88c29542015-11-27 14:57:53 +01004653 /* HACK for unres */
4654 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004655 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004656 /* postpone type resolution when if-feature parsing is done since we need
4657 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004658 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 } else if (!strcmp(sub->name, "default")) {
4660 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004661 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 goto error;
4663 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004664 GETVAL(ctx, value, sub, "value");
4665 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004666
Radek Krejci8d6b7422017-02-03 14:42:13 +01004667 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004668 goto error;
4669 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004670 } else if (!strcmp(sub->name, "units")) {
4671 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004672 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 goto error;
4674 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004675 GETVAL(ctx, value, sub, "name");
4676 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004677
Radek Krejci8d6b7422017-02-03 14:42:13 +01004678 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004679 goto error;
4680 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 } else if (!strcmp(sub->name, "mandatory")) {
4682 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004683 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 goto error;
4685 }
4686 /* just checking the flags in leaf is not sufficient, we would allow
4687 * multiple mandatory statements with the "false" value
4688 */
4689 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004690
Michal Vasko53b7da02018-02-13 15:28:42 +01004691 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004693 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004694 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004695 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004696 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004697 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 goto error;
4699 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004700
Radek Krejci8d6b7422017-02-03 14:42:13 +01004701 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004702 goto error;
4703 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004704 } else if (!strcmp(sub->name, "when")) {
4705 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004706 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004707 goto error;
4708 }
4709
Radek Krejci5323b492017-01-16 15:40:11 +01004710 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004711 if (!leaf->when) {
4712 goto error;
4713 }
4714
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004715 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004716 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004717 c_must++;
4718 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004719 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004720 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004721 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004725 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004728
Michal Vasko88c29542015-11-27 14:57:53 +01004729 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004733 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004734 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 goto error;
4736 }
Michal Vasko478c4652016-07-21 12:55:01 +02004737 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004738 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4739 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004740 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4741 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 /* middle part - process nodes with cardinality of 0..n */
4745 if (c_must) {
4746 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004747 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004749 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004750 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004751 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004752 }
Radek Krejcie534c132016-11-23 13:32:31 +01004753 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004754 /* some extensions may be already present from the substatements */
4755 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004756 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004757 retval->ext = reallocated;
4758
4759 /* init memory */
4760 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004761 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004762
Radek Krejcie534c132016-11-23 13:32:31 +01004763 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4764 if (strcmp(sub->ns->value, LY_NSYIN)) {
4765 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004766 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 +01004767 retval->ext_size++;
4768 if (r) {
4769 goto error;
4770 }
4771 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004772 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004773 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 if (r) {
4775 goto error;
4776 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004777 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004778 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004779 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004780 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004781 goto error;
4782 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004783 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004784 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004785
Radek Krejcicbb473e2016-09-16 14:48:32 +02004786 /* finalize type parsing */
4787 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4788 leaf->type.der = NULL;
4789 goto error;
4790 }
4791
4792 /* check default value (if not defined, there still could be some restrictions
4793 * that need to be checked against a default value from a derived type) */
Michal Vasko6a057782018-03-09 13:24:33 +01004794 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004795 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4796 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004797 goto error;
4798 }
4799
Michal Vasko508a50d2016-09-07 14:50:33 +02004800 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004801 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004802 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004803 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004804 goto error;
4805 }
4806 } else {
4807 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4808 goto error;
4809 }
4810 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004811 }
4812
PavolVican92f23622017-12-12 13:35:56 +01004813 for (r = 0; r < retval->ext_size; ++r) {
4814 /* set flag, which represent LYEXT_OPT_VALID */
4815 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004816 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004817 break;
4818 }
4819 }
4820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004821 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004822
4823error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004824 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004825 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004826}
4827
Michal Vasko0d343d12015-08-24 14:57:36 +02004828/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004829static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004830read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004831 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004832{
Michal Vasko53b7da02018-02-13 15:28:42 +01004833 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004834 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004835 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 struct lyxml_elem *sub, *next;
4837 const char *value;
4838 char *endptr;
4839 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004840 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004841 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004843 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004846 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004847
Radek Krejci76512572015-08-04 09:47:08 +02004848 llist->nodetype = LYS_LEAFLIST;
4849 llist->prev = (struct lys_node *)llist;
4850 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004851
Radek Krejci07d0fb92017-01-13 14:11:05 +01004852 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004853 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4854 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4855 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004856 goto error;
4857 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004858
Michal Vasko3e3228d2017-02-24 14:55:32 +01004859 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004860
Radek Krejcic189a952016-07-11 15:27:07 +02004861 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004862 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004863 goto error;
4864 }
4865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004867 if (strcmp(sub->ns->value, LY_NSYIN)) {
4868 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004869 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004870 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004871 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004872 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004873 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004874 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 goto error;
4876 }
Michal Vasko88c29542015-11-27 14:57:53 +01004877 /* HACK for unres */
4878 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004879 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004880 /* postpone type resolution when if-feature parsing is done since we need
4881 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004882 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 } else if (!strcmp(sub->name, "units")) {
4884 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004885 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004886 goto error;
4887 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004888 GETVAL(ctx, value, sub, "name");
4889 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004890
Radek Krejci8d6b7422017-02-03 14:42:13 +01004891 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004892 goto error;
4893 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 } else if (!strcmp(sub->name, "ordered-by")) {
4895 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004896 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 goto error;
4898 }
4899 /* just checking the flags in llist is not sufficient, we would
4900 * allow multiple ordered-by statements with the "system" value
4901 */
4902 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004903
Radek Krejci1574a8d2015-08-03 14:16:52 +02004904 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4906 * state data
4907 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004908 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 continue;
4910 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004911
Michal Vasko53b7da02018-02-13 15:28:42 +01004912 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004913 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004914 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004916 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004918 } /* else system is the default value, so we can ignore it */
4919
Radek Krejci8d6b7422017-02-03 14:42:13 +01004920 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004921 goto error;
4922 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004923 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004924 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004925 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004926 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004927 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004928 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004929 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004930 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004931 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004932 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004933 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 +01004934 goto error;
4935 }
4936
Michal Vasko53b7da02018-02-13 15:28:42 +01004937 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004938 c_dflt++;
4939 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004940
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004941 } else if (!strcmp(sub->name, "min-elements")) {
4942 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004943 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004944 goto error;
4945 }
4946 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004947
Michal Vasko53b7da02018-02-13 15:28:42 +01004948 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004949 while (isspace(value[0])) {
4950 value++;
4951 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 /* convert it to uint32_t */
4954 errno = 0;
4955 endptr = NULL;
4956 val = strtoul(value, &endptr, 10);
4957 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004958 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004959 goto error;
4960 }
4961 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004962 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004963 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4964 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004965 goto error;
4966 }
Radek Krejci5323b492017-01-16 15:40:11 +01004967
Radek Krejci8d6b7422017-02-03 14:42:13 +01004968 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004969 goto error;
4970 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971 } else if (!strcmp(sub->name, "max-elements")) {
4972 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004973 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 goto error;
4975 }
4976 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004977
Michal Vasko53b7da02018-02-13 15:28:42 +01004978 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 while (isspace(value[0])) {
4980 value++;
4981 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004982
Radek Krejci0d7b2472016-02-12 11:11:03 +01004983 if (!strcmp(value, "unbounded")) {
4984 llist->max = 0;
4985 } else {
4986 /* convert it to uint32_t */
4987 errno = 0;
4988 endptr = NULL;
4989 val = strtoul(value, &endptr, 10);
4990 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004991 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004992 goto error;
4993 }
4994 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004995 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004996 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4997 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004998 goto error;
4999 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005000 }
Radek Krejci5323b492017-01-16 15:40:11 +01005001
Radek Krejci8d6b7422017-02-03 14:42:13 +01005002 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005003 goto error;
5004 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005005 } else if (!strcmp(sub->name, "when")) {
5006 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005007 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005008 goto error;
5009 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005010
Radek Krejci5323b492017-01-16 15:40:11 +01005011 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005012 if (!llist->when) {
5013 goto error;
5014 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005015 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005016 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005019
Michal Vasko88c29542015-11-27 14:57:53 +01005020 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005024 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005025 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005026 goto error;
5027 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005029 /* middle part - process nodes with cardinality of 0..n */
5030 if (c_must) {
5031 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005032 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005033 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005034 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005035 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005036 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005037 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005038 if (c_dflt) {
5039 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005040 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005041 }
Radek Krejcie534c132016-11-23 13:32:31 +01005042 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005043 /* some extensions may be already present from the substatements */
5044 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005045 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005046 retval->ext = reallocated;
5047
5048 /* init memory */
5049 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005050 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005051
Radek Krejcie534c132016-11-23 13:32:31 +01005052 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5053 if (strcmp(sub->ns->value, LY_NSYIN)) {
5054 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005055 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 +01005056 retval->ext_size++;
5057 if (r) {
5058 goto error;
5059 }
5060 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005061 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005062 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005063 if (r) {
5064 goto error;
5065 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005066 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005067 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005068 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005069 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005070 goto error;
5071 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005072 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005073 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005074
Radek Krejciac1a52c2016-09-15 14:42:40 +02005075 /* check for duplicity in case of configuration data,
5076 * in case of status data duplicities are allowed */
5077 if (llist->flags & LYS_CONFIG_W) {
5078 for (r = 0; r < llist->dflt_size; r++) {
5079 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005080 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5081 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005082 goto error;
5083 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005084 }
5085 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005086 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005087 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005088 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005089
Radek Krejcicbb473e2016-09-16 14:48:32 +02005090 /* finalize type parsing */
5091 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5092 llist->type.der = NULL;
5093 goto error;
5094 }
5095
Radek Krejcid5a5c282016-08-15 15:38:08 +02005096 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005097 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5098 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005099 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5100 goto error;
5101 }
5102
5103 /* check default value (if not defined, there still could be some restrictions
5104 * that need to be checked against a default value from a derived type) */
5105 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko6a057782018-03-09 13:24:33 +01005106 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005107 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5108 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005109 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005110 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005111 }
5112
Michal Vasko508a50d2016-09-07 14:50:33 +02005113 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005114 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005115 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005116 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005117 goto error;
5118 }
5119 } else {
5120 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5121 goto error;
5122 }
5123 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005124 }
5125
PavolVican92f23622017-12-12 13:35:56 +01005126 for (r = 0; r < retval->ext_size; ++r) {
5127 /* set flag, which represent LYEXT_OPT_VALID */
5128 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005129 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005130 break;
5131 }
5132 }
5133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005135
5136error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005137 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005139}
5140
Michal Vasko0d343d12015-08-24 14:57:36 +02005141/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005142static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005143read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005144 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005145{
Michal Vasko53b7da02018-02-13 15:28:42 +01005146 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005147 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005148 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005149 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005150 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005151 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005152 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005153 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005154 char *auxs;
5155 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005156 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005158 /* init */
5159 memset(&root, 0, sizeof root);
5160 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005162 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005163 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005164
Radek Krejci76512572015-08-04 09:47:08 +02005165 list->nodetype = LYS_LIST;
5166 list->prev = (struct lys_node *)list;
5167 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005168
Radek Krejci07d0fb92017-01-13 14:11:05 +01005169 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005170 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5171 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5172 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 goto error;
5174 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005175
Michal Vasko3e3228d2017-02-24 14:55:32 +01005176 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005177
Radek Krejcic189a952016-07-11 15:27:07 +02005178 /* insert the node into the schema tree */
5179 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5180 goto error;
5181 }
5182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 /* process list's specific children */
5184 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005185 if (strcmp(sub->ns->value, LY_NSYIN)) {
5186 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005187 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005188 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005189 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005191 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005192 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 !strcmp(sub->name, "leaf-list") ||
5194 !strcmp(sub->name, "leaf") ||
5195 !strcmp(sub->name, "list") ||
5196 !strcmp(sub->name, "choice") ||
5197 !strcmp(sub->name, "uses") ||
5198 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005199 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005200 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005201 !strcmp(sub->name, "action") ||
5202 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005203 lyxml_unlink_elem(ctx, sub, 2);
5204 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005205
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005206 /* array counters */
5207 } else if (!strcmp(sub->name, "key")) {
5208 /* check cardinality 0..1 */
5209 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005210 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 goto error;
5212 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005214 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005215 GETVAL(ctx, value, sub, "value");
5216 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 while ((value = strpbrk(value, " \t\n"))) {
5218 list->keys_size++;
5219 while (isspace(*value)) {
5220 value++;
5221 }
5222 }
5223 list->keys_size++;
5224 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005225 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005226
Radek Krejci8d6b7422017-02-03 14:42:13 +01005227 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005228 goto error;
5229 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005230 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005231 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005232 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005234 lyxml_unlink_elem(ctx, sub, 2);
5235 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005236 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005237 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005238 c_tpdf++;
5239 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005240 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005241 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005242 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005243 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005244 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005246 /* optional stetments */
5247 } else if (!strcmp(sub->name, "ordered-by")) {
5248 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005249 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005250 goto error;
5251 }
5252 /* just checking the flags in llist is not sufficient, we would
5253 * allow multiple ordered-by statements with the "system" value
5254 */
5255 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005256
Radek Krejci1574a8d2015-08-03 14:16:52 +02005257 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005258 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5259 * state data
5260 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005261 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005262 continue;
5263 }
Radek Krejci345ad742015-06-03 11:04:18 +02005264
Michal Vasko53b7da02018-02-13 15:28:42 +01005265 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005266 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005267 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005269 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005271 } /* else system is the default value, so we can ignore it */
5272
Radek Krejci8d6b7422017-02-03 14:42:13 +01005273 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005274 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005275 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005276 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 } else if (!strcmp(sub->name, "min-elements")) {
5278 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005279 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005280 goto error;
5281 }
5282 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005283
Michal Vasko53b7da02018-02-13 15:28:42 +01005284 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 while (isspace(value[0])) {
5286 value++;
5287 }
Radek Krejci345ad742015-06-03 11:04:18 +02005288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 /* convert it to uint32_t */
5290 errno = 0;
5291 auxs = NULL;
5292 val = strtoul(value, &auxs, 10);
5293 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005294 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005295 goto error;
5296 }
5297 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005298 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005299 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5300 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5301 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005302 goto error;
5303 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005304 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005305 goto error;
5306 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005307 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 } else if (!strcmp(sub->name, "max-elements")) {
5309 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005310 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005311 goto error;
5312 }
5313 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005314
Michal Vasko53b7da02018-02-13 15:28:42 +01005315 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 while (isspace(value[0])) {
5317 value++;
5318 }
Radek Krejci345ad742015-06-03 11:04:18 +02005319
Radek Krejci0d7b2472016-02-12 11:11:03 +01005320 if (!strcmp(value, "unbounded")) {
5321 list->max = 0;;
5322 } else {
5323 /* convert it to uint32_t */
5324 errno = 0;
5325 auxs = NULL;
5326 val = strtoul(value, &auxs, 10);
5327 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005328 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005329 goto error;
5330 }
5331 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005332 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005333 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5334 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005335 goto error;
5336 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005337 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005338 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005339 goto error;
5340 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005341 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005342 } else if (!strcmp(sub->name, "when")) {
5343 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005344 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005345 goto error;
5346 }
5347
Radek Krejci5323b492017-01-16 15:40:11 +01005348 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005349 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005350 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005351 goto error;
5352 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005353 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005354 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005355 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005356 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 }
5358 }
Radek Krejci345ad742015-06-03 11:04:18 +02005359
Michal Vaskoe022a562016-09-27 14:24:15 +02005360 /* check - if list is configuration, key statement is mandatory
5361 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005362 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005363 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005364 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005365 goto error;
5366 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005368 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5369 if (c_tpdf) {
5370 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005371 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005372 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005373 if (c_must) {
5374 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005375 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005376 }
5377 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005378 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005379 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005380 }
Radek Krejcie534c132016-11-23 13:32:31 +01005381 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005382 /* some extensions may be already present from the substatements */
5383 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005384 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005385 retval->ext = reallocated;
5386
5387 /* init memory */
5388 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005389 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005390
Radek Krejcie534c132016-11-23 13:32:31 +01005391 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5392 if (strcmp(sub->ns->value, LY_NSYIN)) {
5393 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005394 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 +01005395 retval->ext_size++;
5396 if (r) {
5397 goto error;
5398 }
5399 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005400 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5401 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005402 if (r) {
5403 goto error;
5404 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005405 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005406 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005407 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005408 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005409 goto error;
5410 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005411 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005412 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005413 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005414 if (r) {
5415 goto error;
5416 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005417 }
5418 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005420 /* last part - process data nodes */
5421 LY_TREE_FOR_SAFE(root.child, next, sub) {
5422 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005423 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005424 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005425 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005426 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005427 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005428 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005429 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005430 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005431 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005432 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005433 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005434 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005435 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005437 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005438 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005439 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005440 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005441 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005442 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005443 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005444 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005445 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005446 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005447 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005448 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005449 goto error;
5450 }
Radek Krejci73adb602015-07-02 18:07:40 +02005451
Michal Vasko53b7da02018-02-13 15:28:42 +01005452 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005454
Radek Krejci5c08a992016-11-02 13:30:04 +01005455 if (list->keys_str) {
5456 /* check that we are not in grouping */
5457 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5458 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005459 goto error;
5460 }
5461 } /* 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 +02005462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005463 /* process unique statements */
5464 if (c_uniq) {
5465 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005466 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005467
Radek Krejci461efb92016-02-12 15:52:18 +01005468 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5469 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5470 list->unique_size++;
5471 if (r) {
5472 goto error;
5473 }
5474
Radek Krejci8d6b7422017-02-03 14:42:13 +01005475 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005476 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5477 goto error;
5478 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005479 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005480 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005481 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005482
Michal Vasko508a50d2016-09-07 14:50:33 +02005483 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005484 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005485 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005486 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005487 goto error;
5488 }
5489 } else {
5490 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5491 goto error;
5492 }
5493 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005494 }
5495
PavolVican92f23622017-12-12 13:35:56 +01005496 for (r = 0; r < retval->ext_size; ++r) {
5497 /* set flag, which represent LYEXT_OPT_VALID */
5498 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005499 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005500 break;
5501 }
5502 }
5503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005504 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005505
5506error:
5507
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005508 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005509 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005510 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005511 }
5512 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005513 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005514 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005515
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005516 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005517}
5518
Michal Vasko0d343d12015-08-24 14:57:36 +02005519/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005520static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005521read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005522 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005523{
Michal Vasko53b7da02018-02-13 15:28:42 +01005524 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005525 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005526 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005527 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005528 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005530 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005531 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005532 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005534 /* init */
5535 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005537 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005538 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005539
Radek Krejci76512572015-08-04 09:47:08 +02005540 cont->nodetype = LYS_CONTAINER;
5541 cont->prev = (struct lys_node *)cont;
5542 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005543
Radek Krejci07d0fb92017-01-13 14:11:05 +01005544 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005545 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5546 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5547 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005548 goto error;
5549 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005550
Michal Vasko3e3228d2017-02-24 14:55:32 +01005551 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005552
Radek Krejcic189a952016-07-11 15:27:07 +02005553 /* insert the node into the schema tree */
5554 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5555 goto error;
5556 }
5557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005558 /* process container's specific children */
5559 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005560 if (strcmp(sub->ns->value, LY_NSYIN)) {
5561 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005562 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005563 c_ext++;
5564 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005565 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005566 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005567 goto error;
5568 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005569 GETVAL(ctx, value, sub, "value");
5570 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005571
Radek Krejci8d6b7422017-02-03 14:42:13 +01005572 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005573 goto error;
5574 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005575 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005576 } else if (!strcmp(sub->name, "when")) {
5577 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005578 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005579 goto error;
5580 }
5581
Radek Krejci5323b492017-01-16 15:40:11 +01005582 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005583 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005584 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005585 goto error;
5586 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005587 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005589 /* data statements */
5590 } else if (!strcmp(sub->name, "container") ||
5591 !strcmp(sub->name, "leaf-list") ||
5592 !strcmp(sub->name, "leaf") ||
5593 !strcmp(sub->name, "list") ||
5594 !strcmp(sub->name, "choice") ||
5595 !strcmp(sub->name, "uses") ||
5596 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005597 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005598 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005599 !strcmp(sub->name, "action") ||
5600 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005601 lyxml_unlink_elem(ctx, sub, 2);
5602 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005604 /* array counters */
5605 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005606 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005607 c_tpdf++;
5608 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005609 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005611 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005612 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005613 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005615 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005616 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005617 }
5618 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005620 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5621 if (c_tpdf) {
5622 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005623 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005624 }
5625 if (c_must) {
5626 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005627 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005628 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005629 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005630 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005631 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005632 }
Radek Krejcie534c132016-11-23 13:32:31 +01005633 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005634 /* some extensions may be already present from the substatements */
5635 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005636 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005637 retval->ext = reallocated;
5638
5639 /* init memory */
5640 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005641 }
Radek Krejci800af702015-06-02 13:46:01 +02005642
Radek Krejcie534c132016-11-23 13:32:31 +01005643 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5644 if (strcmp(sub->ns->value, LY_NSYIN)) {
5645 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005646 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 +01005647 retval->ext_size++;
5648 if (r) {
5649 goto error;
5650 }
5651 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005652 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5653 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005654 if (r) {
5655 goto error;
5656 }
5657 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005658 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005659 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005660 if (r) {
5661 goto error;
5662 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005663 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005664 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005665 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005666 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005667 goto error;
5668 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005670 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005672 /* last part - process data nodes */
5673 LY_TREE_FOR_SAFE(root.child, next, sub) {
5674 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005675 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005676 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005677 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005678 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005679 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005680 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005681 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005682 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005683 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005684 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005685 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005686 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005687 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005688 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005689 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005690 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005691 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005692 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005693 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005694 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005695 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005696 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005697 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005698 goto error;
5699 }
Radek Krejci73adb602015-07-02 18:07:40 +02005700
Michal Vasko53b7da02018-02-13 15:28:42 +01005701 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005703
Michal Vasko508a50d2016-09-07 14:50:33 +02005704 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005705 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005706 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005707 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005708 goto error;
5709 }
5710 } else {
5711 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5712 goto error;
5713 }
5714 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005715 }
5716
PavolVican92f23622017-12-12 13:35:56 +01005717 for (r = 0; r < retval->ext_size; ++r) {
5718 /* set flag, which represent LYEXT_OPT_VALID */
5719 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005720 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005721 break;
5722 }
5723 }
5724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005725 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005726
5727error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005728 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005730 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005731 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005732 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005733}
5734
Michal Vasko0d343d12015-08-24 14:57:36 +02005735/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005736static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005737read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005738 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005739{
Michal Vasko53b7da02018-02-13 15:28:42 +01005740 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005741 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005742 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005743 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005744 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005745 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005746 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005747 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749 /* init */
5750 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005752 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005753 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005754
Radek Krejci76512572015-08-04 09:47:08 +02005755 grp->nodetype = LYS_GROUPING;
5756 grp->prev = (struct lys_node *)grp;
5757 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005758
Radek Krejci07d0fb92017-01-13 14:11:05 +01005759 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005760 goto error;
5761 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005762
Michal Vasko3e3228d2017-02-24 14:55:32 +01005763 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005764
Radek Krejcic189a952016-07-11 15:27:07 +02005765 /* insert the node into the schema tree */
5766 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5767 goto error;
5768 }
5769
Radek Krejci1d82ef62015-08-07 14:44:40 +02005770 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005771 if (strcmp(sub->ns->value, LY_NSYIN)) {
5772 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005773 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005774 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005776 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005777 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005778 !strcmp(sub->name, "leaf-list") ||
5779 !strcmp(sub->name, "leaf") ||
5780 !strcmp(sub->name, "list") ||
5781 !strcmp(sub->name, "choice") ||
5782 !strcmp(sub->name, "uses") ||
5783 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005784 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005785 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005786 !strcmp(sub->name, "action") ||
5787 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005788 lyxml_unlink_elem(ctx, sub, 2);
5789 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005791 /* array counters */
5792 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005793 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005794 c_tpdf++;
5795 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005796 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005797 goto error;
5798 }
5799 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005801 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5802 if (c_tpdf) {
5803 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005804 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005805 }
Radek Krejcie534c132016-11-23 13:32:31 +01005806 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005807 /* some extensions may be already present from the substatements */
5808 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005809 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005810 retval->ext = reallocated;
5811
5812 /* init memory */
5813 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005814 }
Radek Krejcie534c132016-11-23 13:32:31 +01005815 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5816 if (strcmp(sub->ns->value, LY_NSYIN)) {
5817 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005818 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 +01005819 retval->ext_size++;
5820 if (r) {
5821 goto error;
5822 }
5823 } else {
5824 /* typedef */
5825 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5826 grp->tpdf_size++;
5827 if (r) {
5828 goto error;
5829 }
5830 }
5831 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005833 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005834 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005835 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005836 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005837 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005838 LY_TREE_FOR_SAFE(root.child, next, sub) {
5839 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005840 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005841 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005842 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005843 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005844 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005845 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005846 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005847 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005848 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005849 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005850 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005851 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005852 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005853 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005854 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005855 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005856 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005857 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005858 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005859 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005860 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005861 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005862 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005863 goto error;
5864 }
Radek Krejci73adb602015-07-02 18:07:40 +02005865
Michal Vasko53b7da02018-02-13 15:28:42 +01005866 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005867 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005869 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005870
5871error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005872 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005873 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005874 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005875 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005876 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005877}
5878
Michal Vasko0d343d12015-08-24 14:57:36 +02005879/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005880static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005881read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005882 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005883{
Michal Vasko53b7da02018-02-13 15:28:42 +01005884 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005885 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005886 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005887 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005888 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005889 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005890 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005891
Radek Krejcie0674f82015-06-15 13:58:51 +02005892 /* init */
5893 memset(&root, 0, sizeof root);
5894
Michal Vasko38d01f72015-06-15 09:41:06 +02005895 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005896 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005897 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005898
5899 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005900 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005901 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005902 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005903 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005904 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005905 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005906 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005907 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005908 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005909 }
5910
Radek Krejci76512572015-08-04 09:47:08 +02005911 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005912 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005913
Michal Vasko3e3228d2017-02-24 14:55:32 +01005914 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005915
Radek Krejcic189a952016-07-11 15:27:07 +02005916 /* insert the node into the schema tree */
5917 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5918 goto error;
5919 }
5920
Michal Vasko38d01f72015-06-15 09:41:06 +02005921 /* data statements */
5922 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005923 if (!sub->ns) {
5924 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005925 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005926 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005927 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005928 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005929 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005930 c_ext++;
5931 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005932 !strcmp(sub->name, "leaf-list") ||
5933 !strcmp(sub->name, "leaf") ||
5934 !strcmp(sub->name, "list") ||
5935 !strcmp(sub->name, "choice") ||
5936 !strcmp(sub->name, "uses") ||
5937 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005938 !strcmp(sub->name, "anyxml") ||
5939 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005940 lyxml_unlink_elem(ctx, sub, 2);
5941 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005943 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005944 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005945 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02005946 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005947 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005948
Radek Krejci1a31efe2016-07-29 11:04:16 +02005949 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005950 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02005951 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02005952 c_must++;
5953
Michal Vasko38d01f72015-06-15 09:41:06 +02005954 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005955 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005956 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005957 }
5958 }
5959
5960 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5961 if (c_tpdf) {
5962 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005963 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005964 }
Radek Krejci19332802016-07-29 10:39:46 +02005965 if (c_must) {
5966 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005967 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02005968 }
Radek Krejcie534c132016-11-23 13:32:31 +01005969 if (c_ext) {
5970 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005971 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01005972 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005973
Radek Krejcie534c132016-11-23 13:32:31 +01005974 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5975 if (strcmp(sub->ns->value, LY_NSYIN)) {
5976 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005977 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 +01005978 retval->ext_size++;
5979 if (r) {
5980 goto error;
5981 }
5982 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005983 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005984 inout->must_size++;
5985 if (r) {
5986 goto error;
5987 }
5988 } else { /* typedef */
5989 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5990 inout->tpdf_size++;
5991 if (r) {
5992 goto error;
5993 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005994 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005995 }
5996
5997 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005998 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02005999 LY_TREE_FOR_SAFE(root.child, next, sub) {
6000 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006001 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006002 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006003 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006004 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006005 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006006 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006007 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006008 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006009 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006010 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006011 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006012 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006013 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006014 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006015 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006016 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006017 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006018 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006019 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006020 goto error;
6021 }
Radek Krejci73adb602015-07-02 18:07:40 +02006022
Michal Vasko53b7da02018-02-13 15:28:42 +01006023 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006024 }
6025
Michal Vasko508a50d2016-09-07 14:50:33 +02006026 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006027 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006028 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006029 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006030 goto error;
6031 }
6032 } else {
6033 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6034 goto error;
6035 }
6036 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006037 }
6038
Michal Vasko38d01f72015-06-15 09:41:06 +02006039 return retval;
6040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006041error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006042 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006043 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006044 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006045 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006046 return NULL;
6047}
6048
Michal Vasko0d343d12015-08-24 14:57:36 +02006049/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006050static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006051read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006052 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006053{
Michal Vasko53b7da02018-02-13 15:28:42 +01006054 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006055 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006056 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006057 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006058 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006059 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006060 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006061 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006062
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006063 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006064 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006065 return NULL;
6066 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006067
Michal Vaskoc6551b32015-06-16 10:51:43 +02006068 memset(&root, 0, sizeof root);
6069
Michal Vasko0ea41032015-06-16 08:53:55 +02006070 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006071 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006072
Radek Krejci76512572015-08-04 09:47:08 +02006073 notif->nodetype = LYS_NOTIF;
6074 notif->prev = (struct lys_node *)notif;
6075 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006076
Radek Krejci07d0fb92017-01-13 14:11:05 +01006077 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006078 goto error;
6079 }
6080
Michal Vasko3e3228d2017-02-24 14:55:32 +01006081 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006082
Radek Krejcic189a952016-07-11 15:27:07 +02006083 /* insert the node into the schema tree */
6084 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6085 goto error;
6086 }
6087
Michal Vasko0ea41032015-06-16 08:53:55 +02006088 /* process rpc's specific children */
6089 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006090 if (strcmp(sub->ns->value, LY_NSYIN)) {
6091 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006092 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006093 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006094 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006095
Michal Vasko0ea41032015-06-16 08:53:55 +02006096 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006097 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006098 !strcmp(sub->name, "leaf-list") ||
6099 !strcmp(sub->name, "leaf") ||
6100 !strcmp(sub->name, "list") ||
6101 !strcmp(sub->name, "choice") ||
6102 !strcmp(sub->name, "uses") ||
6103 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006104 !strcmp(sub->name, "anyxml") ||
6105 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006106 lyxml_unlink_elem(ctx, sub, 2);
6107 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006109 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006110 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006111 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006112 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006113 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006114 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006115 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006116 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006117 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006118 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006119 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006120 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006121 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006122 }
6123 }
6124
6125 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6126 if (c_tpdf) {
6127 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006128 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006129 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006130 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006131 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006132 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006133 }
Radek Krejci19332802016-07-29 10:39:46 +02006134 if (c_must) {
6135 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006136 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006137 }
Radek Krejcie534c132016-11-23 13:32:31 +01006138 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006139 /* some extensions may be already present from the substatements */
6140 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006141 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006142 retval->ext = reallocated;
6143
6144 /* init memory */
6145 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006146 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006147
Radek Krejcie534c132016-11-23 13:32:31 +01006148 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6149 if (strcmp(sub->ns->value, LY_NSYIN)) {
6150 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006151 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 +01006152 retval->ext_size++;
6153 if (r) {
6154 goto error;
6155 }
6156 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006157 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6158 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006159 if (r) {
6160 goto error;
6161 }
Radek Krejci96299152016-06-22 10:17:50 +02006162 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006163 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006164 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006165 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006166 goto error;
6167 }
Radek Krejci19332802016-07-29 10:39:46 +02006168 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006169 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006170 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006171 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006172 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006173 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006174 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006175 }
6176
6177 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006178 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006179 LY_TREE_FOR_SAFE(root.child, next, sub) {
6180 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006181 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006182 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006183 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006184 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006185 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006186 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006187 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006188 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006189 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006190 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006191 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006192 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006193 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006194 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006195 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006196 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006197 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006198 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006199 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006200 goto error;
6201 }
Radek Krejci73adb602015-07-02 18:07:40 +02006202
Michal Vasko53b7da02018-02-13 15:28:42 +01006203 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006204 }
6205
Michal Vasko508a50d2016-09-07 14:50:33 +02006206 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006207 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006208 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006209 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006210 goto error;
6211 }
6212 } else {
6213 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6214 goto error;
6215 }
6216 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006217 }
6218
Michal Vasko0ea41032015-06-16 08:53:55 +02006219 return retval;
6220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006221error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006222 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006223 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006224 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006225 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006226 return NULL;
6227}
6228
Michal Vasko0d343d12015-08-24 14:57:36 +02006229/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006230static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006231read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006232 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006233{
Michal Vasko53b7da02018-02-13 15:28:42 +01006234 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006235 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006236 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006237 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006238 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006239 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006240 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006241 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006242
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006243 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006244 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006245 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006246 return NULL;
6247 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006248 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006249 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006250 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006251 LOGVAL(ctx, LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006252 return NULL;
6253 }
6254 }
6255 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006256
Radek Krejcie0674f82015-06-15 13:58:51 +02006257 /* init */
6258 memset(&root, 0, sizeof root);
6259
Michal Vasko38d01f72015-06-15 09:41:06 +02006260 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006261 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006262
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006263 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006264 rpc->prev = (struct lys_node *)rpc;
6265 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006266
Radek Krejci07d0fb92017-01-13 14:11:05 +01006267 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006268 goto error;
6269 }
6270
Michal Vasko3e3228d2017-02-24 14:55:32 +01006271 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006272
Radek Krejcic189a952016-07-11 15:27:07 +02006273 /* insert the node into the schema tree */
6274 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6275 goto error;
6276 }
6277
Michal Vasko38d01f72015-06-15 09:41:06 +02006278 /* process rpc's specific children */
6279 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006280 if (strcmp(sub->ns->value, LY_NSYIN)) {
6281 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006282 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006283 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006284 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006285 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006286 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006287 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006288 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006289 goto error;
6290 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006291 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006292 lyxml_unlink_elem(ctx, sub, 2);
6293 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006294 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006295 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006296 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006297 goto error;
6298 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006299 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006300 lyxml_unlink_elem(ctx, sub, 2);
6301 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006303 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006304 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006305 lyxml_unlink_elem(ctx, sub, 2);
6306 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006308 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006309 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006310 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006311 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006312 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006313 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006314 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006315 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006316 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006317 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006318 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006319 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006320 }
6321 }
6322
6323 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6324 if (c_tpdf) {
6325 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006326 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006327 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006328 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006329 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006330 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006331 }
Radek Krejcie534c132016-11-23 13:32:31 +01006332 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006333 /* some extensions may be already present from the substatements */
6334 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006335 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006336 retval->ext = reallocated;
6337
6338 /* init memory */
6339 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006340 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006341
Radek Krejcie534c132016-11-23 13:32:31 +01006342 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6343 if (strcmp(sub->ns->value, LY_NSYIN)) {
6344 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006345 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 +01006346 retval->ext_size++;
6347 if (r) {
6348 goto error;
6349 }
6350 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006351 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6352 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006353 if (r) {
6354 goto error;
6355 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006356 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006357 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006358 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006359 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006360 goto error;
6361 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006362 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006363 }
6364
6365 /* last part - process data nodes */
6366 LY_TREE_FOR_SAFE(root.child, next, sub) {
6367 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006368 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006369 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006370 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006371 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006372 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006373 goto error;
6374 }
Radek Krejci73adb602015-07-02 18:07:40 +02006375
Michal Vasko53b7da02018-02-13 15:28:42 +01006376 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006377 }
6378
Michal Vasko38d01f72015-06-15 09:41:06 +02006379 return retval;
6380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006381error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006382 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006383 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006384 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006385 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006386 return NULL;
6387}
6388
Michal Vasko0d343d12015-08-24 14:57:36 +02006389/* logs directly
6390 *
Radek Krejci74705112015-06-05 10:25:44 +02006391 * resolve - referenced grouping should be bounded to the namespace (resolved)
6392 * only when uses does not appear in grouping. In a case of grouping's uses,
6393 * we just get information but we do not apply augment or refine to it.
6394 */
Radek Krejci76512572015-08-04 09:47:08 +02006395static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006396read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6397 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006398{
Michal Vasko53b7da02018-02-13 15:28:42 +01006399 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006400 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006401 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006402 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006403 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006404 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006405 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006406 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006408 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006409 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006410
Radek Krejci76512572015-08-04 09:47:08 +02006411 uses->nodetype = LYS_USES;
6412 uses->prev = (struct lys_node *)uses;
6413 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006414
Michal Vasko53b7da02018-02-13 15:28:42 +01006415 GETVAL(ctx, value, yin, "name");
6416 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006417
Radek Krejci07d0fb92017-01-13 14:11:05 +01006418 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006419 goto error;
6420 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006421
Michal Vasko3e3228d2017-02-24 14:55:32 +01006422 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006423
Radek Krejcic189a952016-07-11 15:27:07 +02006424 /* insert the node into the schema tree */
6425 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6426 goto error;
6427 }
6428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006429 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006430 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006431 if (strcmp(sub->ns->value, LY_NSYIN)) {
6432 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006433 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006434 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006435 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006436 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006437 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006438 c_ref++;
6439 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006440 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006441 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006442 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006443 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006444 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006445 } else if (!strcmp(sub->name, "when")) {
6446 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006447 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006448 goto error;
6449 }
6450
Radek Krejci5323b492017-01-16 15:40:11 +01006451 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006452 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006453 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006454 goto error;
6455 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006456 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006457 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006458 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006459 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006460 }
6461 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006463 /* process properties with cardinality 0..n */
6464 if (c_ref) {
6465 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006466 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006467 }
6468 if (c_aug) {
6469 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006470 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006471 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006472 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006473 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006474 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006475 }
Radek Krejcie534c132016-11-23 13:32:31 +01006476 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006477 /* some extensions may be already present from the substatements */
6478 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006479 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006480 retval->ext = reallocated;
6481
6482 /* init memory */
6483 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006484 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006485
Radek Krejcie534c132016-11-23 13:32:31 +01006486 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6487 if (strcmp(sub->ns->value, LY_NSYIN)) {
6488 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006489 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 +01006490 retval->ext_size++;
6491 if (r) {
6492 goto error;
6493 }
6494 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006495 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006496 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006497 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006498 goto error;
6499 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006500 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006501 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006502 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006503 if (r) {
6504 goto error;
6505 }
6506 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006507 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006508 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006509 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006510 goto error;
6511 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006512 }
6513 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006514
Radek Krejci48464ed2016-03-17 15:44:09 +01006515 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006516 goto error;
6517 }
Radek Krejci74705112015-06-05 10:25:44 +02006518
Michal Vasko508a50d2016-09-07 14:50:33 +02006519 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006520 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006521 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006522 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006523 goto error;
6524 }
6525 } else {
6526 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6527 goto error;
6528 }
6529 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006530 }
6531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006532 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006533
6534error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006535 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006536 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006537}
6538
Michal Vasko0d343d12015-08-24 14:57:36 +02006539/* logs directly
6540 *
6541 * common code for yin_read_module() and yin_read_submodule()
6542 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006543static int
Radek Krejcic071c542016-01-27 14:57:51 +01006544read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6545 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006546{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006547 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006548 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006549 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006550 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006551 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006552 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006553 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006554 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6555 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6556 int substmt_group;
6557 /* just remember last substatement for logging */
6558 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006559 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006560 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;
6561 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006562 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006563
Radek Krejcic071c542016-01-27 14:57:51 +01006564 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006565 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006567 /* init */
6568 memset(&root, 0, sizeof root);
6569 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006570 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006571 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006572 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006574 /*
6575 * in the first run, we process elements with cardinality of 1 or 0..1 and
6576 * count elements with cardinality 0..n. Data elements (choices, containers,
6577 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6578 * need have all top-level and groupings already prepared at that time. In
6579 * the middle loop, we process other elements with carinality of 0..n since
6580 * we need to allocate arrays to store them.
6581 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006582 substmt_group = 0;
6583 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006584 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006585 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006586 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006587 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006588 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006589 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006590 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006591 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006592 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006593 lyxml_unlink_elem(ctx, child, 2);
6594 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006595 c_extinst++;
6596 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006597 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006598 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6599 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006600 child->name, substmt_prev);
6601 goto error;
6602 }
6603
PavolVican9e81c6a2017-02-09 13:09:07 +01006604 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006605 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006606 goto error;
6607 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006608 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006609 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006610
Radek Krejci8d6b7422017-02-03 14:42:13 +01006611 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006612 goto error;
6613 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006614 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006615
6616 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006617 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006618 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006619 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6620 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006621 child->name, substmt_prev);
6622 goto error;
6623 }
6624
PavolVican9e81c6a2017-02-09 13:09:07 +01006625 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006626 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006627 goto error;
6628 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006629 GETVAL(ctx, value, child, "value");
6630 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006631 goto error;
6632 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006633 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006634
Radek Krejci8d6b7422017-02-03 14:42:13 +01006635 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006636 goto error;
6637 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006638 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006639
6640 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006641 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006642 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006643 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6644 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006645 child->name, substmt_prev);
6646 goto error;
6647 }
6648
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006649 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006650 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006651 goto error;
6652 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006653 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006654 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006655 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006656 goto error;
6657 }
Radek Krejcif3886932015-06-04 17:36:06 +02006658
Radek Krejci8d6b7422017-02-03 14:42:13 +01006659 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006660 goto error;
6661 }
6662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006663 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006664 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006665 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006666 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006667 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006668 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006669 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006670 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006671 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006672 goto error;
6673 }
6674 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006675 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006676 /* check here differs from a generic prefix check, since this prefix
6677 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006678 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006679 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006680 goto error;
6681 }
Radek Krejcic071c542016-01-27 14:57:51 +01006682 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006683
Radek Krejci8d6b7422017-02-03 14:42:13 +01006684 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 +01006685 goto error;
6686 }
6687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006688 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006689 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006690
Michal Vasko5de8a022017-02-08 10:57:26 +01006691 substmt_prev = "belongs-to";
6692
Radek Krejcieb00f512015-07-01 16:44:58 +02006693 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006694 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006695 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006696 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6697 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006698 child->name, substmt_prev);
6699 goto error;
6700 }
6701 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006702 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006703 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006704 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006705
6706 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006707 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006708 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006709 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6710 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006711 child->name, substmt_prev);
6712 goto error;
6713 }
6714 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006715 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006716 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006717 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006718
PavolVican9e81c6a2017-02-09 13:09:07 +01006719 lyxml_unlink_elem(ctx, child, 2);
6720 lyxml_add_child(ctx, &revs, child);
6721
Michal Vasko5de8a022017-02-08 10:57:26 +01006722 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006723 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006724 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006725 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006726 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006727 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006728
6729 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006730 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006731 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006732 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006733 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006734 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006735
6736 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006737 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006738 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006739 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6740 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006741 child->name, substmt_prev);
6742 goto error;
6743 }
6744 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006745 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006746 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006747 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006748
6749 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006750 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006751 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006752 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006753 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006754 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006755 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006756 lyxml_unlink_elem(ctx, child, 2);
6757 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006758
Michal Vasko5de8a022017-02-08 10:57:26 +01006759 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006760 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006761 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006762 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006763 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006764 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006765
Michal Vasko5de8a022017-02-08 10:57:26 +01006766 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006768 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006769 } else if (!strcmp(child->name, "container") ||
6770 !strcmp(child->name, "leaf-list") ||
6771 !strcmp(child->name, "leaf") ||
6772 !strcmp(child->name, "list") ||
6773 !strcmp(child->name, "choice") ||
6774 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006775 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006776 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006777 !strcmp(child->name, "rpc") ||
6778 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006779 substmt_group = 4;
6780
Radek Krejcic071c542016-01-27 14:57:51 +01006781 lyxml_unlink_elem(ctx, child, 2);
6782 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006783
Michal Vasko5de8a022017-02-08 10:57:26 +01006784 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006785 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006786 substmt_group = 4;
6787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006788 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006789 lyxml_unlink_elem(ctx, child, 2);
6790 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006791
Michal Vasko5de8a022017-02-08 10:57:26 +01006792 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006793 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006794 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006795 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006796 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6797 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006798 child->name, substmt_prev);
6799 goto error;
6800 }
6801 substmt_group = 2;
6802
Radek Krejcic071c542016-01-27 14:57:51 +01006803 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006804 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006805 goto error;
6806 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006807 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006808 goto error;
6809 }
Radek Krejcic071c542016-01-27 14:57:51 +01006810 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006811 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006812 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006813 goto error;
6814 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006815
6816 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006817 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006818 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006819 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6820 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006821 child->name, substmt_prev);
6822 goto error;
6823 }
6824 substmt_group = 2;
6825
Radek Krejcic071c542016-01-27 14:57:51 +01006826 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006827 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006828 goto error;
6829 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006830 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006831 goto error;
6832 }
Radek Krejcic071c542016-01-27 14:57:51 +01006833 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006834 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006835 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006836 goto error;
6837 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006838
6839 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006840 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006841 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006842 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6843 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006844 child->name, substmt_prev);
6845 goto error;
6846 }
6847 substmt_group = 2;
6848
Radek Krejcic071c542016-01-27 14:57:51 +01006849 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006850 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006851 goto error;
6852 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006853 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006854 goto error;
6855 }
Radek Krejcic071c542016-01-27 14:57:51 +01006856 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006857 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006858 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006859 goto error;
6860 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006861
6862 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006863 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006864 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006865 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6866 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006867 child->name, substmt_prev);
6868 goto error;
6869 }
6870 substmt_group = 2;
6871
Radek Krejcic071c542016-01-27 14:57:51 +01006872 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006873 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006874 goto error;
6875 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006876 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006877 goto error;
6878 }
Radek Krejcic071c542016-01-27 14:57:51 +01006879 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006880 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006881 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006882 goto error;
6883 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006884
6885 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006886 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006887 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006888 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6889 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006890 child->name, substmt_prev);
6891 goto error;
6892 }
6893
Radek Krejcic071c542016-01-27 14:57:51 +01006894 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006895 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006896 goto error;
6897 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006898 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006899 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006900 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006901 goto error;
6902 }
Radek Krejcic071c542016-01-27 14:57:51 +01006903 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006904 if (!strcmp(value, "1")) {
6905 if (submodule) {
6906 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006907 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006908 goto error;
6909 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006910 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006911 } else {
6912 module->version = 1;
6913 }
6914 } else {
6915 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006916 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006917 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006918 goto error;
6919 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006920 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006921 } else {
6922 module->version = 2;
6923 }
6924 }
6925
Radek Krejci8d6b7422017-02-03 14:42:13 +01006926 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006927 goto error;
6928 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006929 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006930
Michal Vasko5de8a022017-02-08 10:57:26 +01006931 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006932 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006933 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006934 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006935 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006936 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006937
Michal Vasko5de8a022017-02-08 10:57:26 +01006938 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006939 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006940 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006941 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006942 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006943 c_dev++;
6944
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006945 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006946 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006947 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006948 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006949 }
6950 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006951
Radek Krejcic071c542016-01-27 14:57:51 +01006952 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006953 if (submodule) {
6954 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006955 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006956 goto error;
6957 }
6958 if (!version_flag) {
6959 /* check version compatibility with the main module */
6960 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006961 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006962 goto error;
6963 }
6964 }
6965 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006966 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006967 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006968 goto error;
6969 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006970 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006971 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006972 goto error;
6973 }
6974 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006976 /* allocate arrays for elements with cardinality of 0..n */
6977 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006978 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01006979 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006980 }
6981 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006982 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01006983 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006984 }
6985 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006986 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006987 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006988 }
6989 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006990 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01006991 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006992 }
6993 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006994 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006995 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006996 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006997 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006998 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006999 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007000 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02007001 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01007002 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007003 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007004 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007005 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007006 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007007 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007008 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007009 if (c_ext) {
7010 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007011 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007012 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007013
PavolVican9e81c6a2017-02-09 13:09:07 +01007014 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7015 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007016 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7017 trg->rev_size++;
7018 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007019 goto error;
7020 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007021
Radek Krejci7417a082017-02-16 11:07:59 +01007022 /* check uniqueness of the revision date - not required by RFC */
7023 for (i = 0; i < (trg->rev_size - 1); i++) {
7024 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007025 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007026 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007027 }
7028 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007029
7030 lyxml_free(ctx, child);
7031 }
7032
7033 /* check the module with respect to the context now */
7034 if (!submodule) {
7035 switch (lyp_ctx_check_module(module)) {
7036 case -1:
7037 goto error;
7038 case 0:
7039 break;
7040 case 1:
7041 /* it's already there */
7042 ret = 1;
7043 goto error;
7044 }
7045 }
7046
PavolVican92f23622017-12-12 13:35:56 +01007047 /* check first definition of extensions */
7048 if (c_ext) {
7049 LY_TREE_FOR_SAFE(yin->child, next, child) {
7050 if (!strcmp(child->name, "extension")) {
7051 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7052 trg->extensions_size++;
7053 if (r) {
7054 goto error;
7055 }
7056
7057 }
7058 }
7059 }
7060
PavolVican9e81c6a2017-02-09 13:09:07 +01007061 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007062 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007063 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007064 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007065 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007066 if (r) {
7067 goto error;
7068 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007069
Radek Krejci1d82ef62015-08-07 14:44:40 +02007070 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007071 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7072 trg->inc_size++;
7073 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007074 goto error;
7075 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007076
Radek Krejci1d82ef62015-08-07 14:44:40 +02007077 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007078 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7079 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007080 if (r) {
7081 goto error;
7082 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007083
Radek Krejci1d82ef62015-08-07 14:44:40 +02007084 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007085 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7086 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007087 if (r) {
7088 goto error;
7089 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007090
Radek Krejci1d82ef62015-08-07 14:44:40 +02007091 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007092 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7093 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007094 if (r) {
7095 goto error;
7096 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007097
Radek Krejci1d82ef62015-08-07 14:44:40 +02007098 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko0f437062018-06-08 15:52:39 +02007099 /* must be implemented in this case */
7100 trg->implemented = 1;
7101
Radek Krejcic071c542016-01-27 14:57:51 +01007102 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7103 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007104 if (r) {
7105 goto error;
7106 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007107 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007108 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007109
Radek Krejcie534c132016-11-23 13:32:31 +01007110 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007111 if (c_extinst) {
7112 /* some extensions may be already present from the substatements */
7113 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007114 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007115 trg->ext = reallocated;
7116
7117 /* init memory */
7118 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7119
7120 LY_TREE_FOR_SAFE(exts.child, next, child) {
7121 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7122 trg->ext_size++;
7123 if (r) {
7124 goto error;
7125 }
7126 }
Radek Krejcie534c132016-11-23 13:32:31 +01007127 }
7128
Radek Krejcif5be10f2015-06-16 13:29:36 +02007129 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007130 * refer to them. Submodule's data nodes are stored in the
7131 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007132 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007133 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007134 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007135 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007136 goto error;
7137 }
Radek Krejci74705112015-06-05 10:25:44 +02007138
Michal Vasko345da0a2015-12-02 10:35:55 +01007139 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007140 }
Radek Krejci74705112015-06-05 10:25:44 +02007141
Radek Krejcif5be10f2015-06-16 13:29:36 +02007142 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007143 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007144
Radek Krejci1d82ef62015-08-07 14:44:40 +02007145 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007146 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007147 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007148 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007149 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007150 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007151 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007152 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007153 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007154 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007155 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007156 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007157 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007158 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007159 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007160 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007161 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007162 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007163 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007164 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007165 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007166 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007167 goto error;
7168 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007169
Michal Vasko345da0a2015-12-02 10:35:55 +01007170 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007171 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007172
Michal Vasko2f7925f2015-10-21 15:06:56 +02007173 /* ... and finally augments (last, so we can augment our data, for instance) */
7174 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007175 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007176 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007177
Michal Vasko2f7925f2015-10-21 15:06:56 +02007178 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007179 goto error;
7180 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007181 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007182 }
7183
PavolVican9e81c6a2017-02-09 13:09:07 +01007184 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007185
7186error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007187 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007188 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007189 }
7190 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007191 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007192 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007193 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007194 lyxml_free(ctx, augs.child);
7195 }
7196 while (revs.child) {
7197 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007198 }
Radek Krejcie534c132016-11-23 13:32:31 +01007199 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007200 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007201 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007202
PavolVican9e81c6a2017-02-09 13:09:07 +01007203 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007204}
7205
Michal Vasko0d343d12015-08-24 14:57:36 +02007206/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007207struct lys_submodule *
7208yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007209{
Michal Vasko53b7da02018-02-13 15:28:42 +01007210 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007211 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007212 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007213 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007214
Michal Vasko53b7da02018-02-13 15:28:42 +01007215 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007216 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007217 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007218 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007220 /* check root element */
7221 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007222 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007223 goto error;
7224 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007225
Michal Vasko53b7da02018-02-13 15:28:42 +01007226 GETVAL(ctx, value, yin, "name");
7227 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007228 goto error;
7229 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007230
Michal Vasko5a721fd2016-02-16 12:16:48 +01007231 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007232 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007233
Michal Vasko53b7da02018-02-13 15:28:42 +01007234 submodule->ctx = ctx;
7235 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007236 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007237 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007238 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007239
Radek Krejci9e757e02017-03-08 17:18:09 +01007240 /* add into the list of processed modules */
7241 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7242 goto error;
7243 }
7244
Michal Vasko5a721fd2016-02-16 12:16:48 +01007245 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007246 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007247 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007248 goto error;
7249 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007250
Radek Krejci33fc4772017-01-26 16:00:35 +01007251 lyp_sort_revisions((struct lys_module *)submodule);
7252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007253 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007254 lyxml_free(ctx, yin);
7255 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007256
Michal Vasko5a721fd2016-02-16 12:16:48 +01007257 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007258 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007259
7260error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007261 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007262 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007263 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007264 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007265 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007266 }
7267
Michal Vasko53b7da02018-02-13 15:28:42 +01007268 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007269
Michal Vaskoa9728122018-01-16 14:00:13 +01007270 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007271 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007272 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7273 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007274 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007275 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007276}
7277
Michal Vasko0d343d12015-08-24 14:57:36 +02007278/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007279struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007280yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007281{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007282 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007283 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007284 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007285 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007286
Radek Krejcic071c542016-01-27 14:57:51 +01007287 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007288 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007290 /* check root element */
7291 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007292 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007293 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007294 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007295 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007296 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007297 goto error;
7298 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007299
Michal Vasko53b7da02018-02-13 15:28:42 +01007300 GETVAL(ctx, value, yin, "name");
7301 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007302 goto error;
7303 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007305 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007306 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007308 module->ctx = ctx;
7309 module->name = lydict_insert(ctx, value, strlen(value));
7310 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007311 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007312
Radek Krejci9e757e02017-03-08 17:18:09 +01007313 /* add into the list of processed modules */
7314 if (lyp_check_circmod_add(module)) {
7315 goto error;
7316 }
7317
Michal Vasko9f258e42016-02-11 11:36:27 +01007318 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007319 ret = read_sub_module(module, NULL, yin, unres);
7320 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007321 goto error;
7322 }
7323
PavolVican9e81c6a2017-02-09 13:09:07 +01007324 if (ret == 1) {
7325 assert(!unres->count);
7326 } else {
Michal Vasko0f437062018-06-08 15:52:39 +02007327 /* make this module implemented if was not from start */
7328 if (!implement && module->implemented && (unres_schema_add_node(module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1)) {
7329 goto error;
7330 }
7331
PavolVican9e81c6a2017-02-09 13:09:07 +01007332 /* resolve rest of unres items */
7333 if (unres->count && resolve_unres_schema(module, unres)) {
7334 goto error;
7335 }
7336
7337 /* check correctness of includes */
7338 if (lyp_check_include_missing(module)) {
7339 goto error;
7340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007341 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007342
Radek Krejci95f22ae2017-01-20 14:25:53 +01007343 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007344
7345 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7346 goto error;
7347 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007348
Radek Krejciff4874d2016-03-07 12:30:50 +01007349 if (revision) {
7350 /* check revision of the parsed model */
7351 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007352 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7353 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007354 goto error;
7355 }
7356 }
7357
PavolVican9e81c6a2017-02-09 13:09:07 +01007358 /* add into context if not already there */
7359 if (!ret) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007360 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007361 goto error;
7362 }
Michal Vasko10681e82018-01-16 14:54:16 +01007363
7364 /* remove our submodules from the parsed submodules list */
7365 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007366 } else {
7367 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007368 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007369
7370 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007371 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007372 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007373 }
7374
Michal Vasko44ab1462017-05-18 13:18:36 +02007375 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007376 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007377 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7378 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007379 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007380
7381error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007382 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007383 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007384
7385 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007386 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7387 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007388 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007389 return NULL;
7390 }
7391
Michal Vasko53b7da02018-02-13 15:28:42 +01007392 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007393
Radek Krejci9e757e02017-03-08 17:18:09 +01007394 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007395 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007396 lyp_del_includedup(module, 1);
7397 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007398 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007399}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007400
Radek Krejci37f9ba32017-02-10 16:50:35 +01007401/* logs directly */
7402struct lys_module *
7403yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7404{
7405 struct lyxml_elem *yin;
7406 struct lys_module *result;
7407
Radek Krejcie1bacd72017-03-01 13:18:46 +01007408 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007409 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007410 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007411 return NULL;
7412 }
7413
7414 result = yin_read_module_(ctx, yin, revision, implement);
7415
7416 lyxml_free(ctx, yin);
7417
7418 return result;
7419}
7420
Radek Krejcic1885952017-02-07 09:37:51 +01007421static int
7422yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007423 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007424 const char *true_val, const char *false_val, struct unres_schema *unres)
7425{
7426 uint8_t *val;
7427 const char *str;
7428 struct lyext_substmt *info;
7429
7430 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7431 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007432 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007433 return EXIT_FAILURE;
7434 }
7435 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007436 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007437 return EXIT_FAILURE;
7438 }
7439
Radek Krejcidb35f172017-02-27 11:03:01 +01007440 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007441 return EXIT_FAILURE;
7442 }
7443
7444 str = lyxml_get_attr(node, "value", NULL);
7445 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007446 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007447 } else if (true_val && !strcmp(true_val, str)) {
7448 /* true value */
7449 *val = 1;
7450 } else if (false_val && !strcmp(false_val, str)) {
7451 /* false value */
7452 *val = 2;
7453 } else {
7454 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007455 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007456 return EXIT_FAILURE;
7457 }
7458
7459 return EXIT_SUCCESS;
7460}
7461
Radek Krejci8d6b7422017-02-03 14:42:13 +01007462/*
7463 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7464 * argname - name of the element/attribute where the value is stored
7465 */
7466static int
7467yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007468 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007469 int argelem, const char *argname, struct unres_schema *unres)
7470{
7471 int c;
PavolVican99c70722017-02-18 17:25:52 +01007472 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007473 void *reallocated;
7474 struct lyext_substmt *info;
7475
7476 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7477 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007478 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007479 return EXIT_FAILURE;
7480 }
7481 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007482 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007483 return EXIT_FAILURE;
7484 }
7485
7486 c = 0;
7487 if (info->cardinality >= LY_STMT_CARD_SOME) {
7488 /* there can be multiple instances, str is actually const char *** */
7489 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007490 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007491 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007492 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007493 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007494 if (stmt == LY_STMT_BELONGSTO) {
7495 /* allocate another array for the belongs-to's prefixes */
7496 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007497 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007498 } else if (stmt == LY_STMT_ARGUMENT) {
7499 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007500 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007501 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007502 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007503 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007504 /* get the index in the array to add new item */
7505 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007506 }
Radek Krejci56c80412017-02-09 10:44:16 +01007507 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007508 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007509 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007510 return EXIT_FAILURE;
7511 }
7512
7513 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007514 str[c] = read_yin_subnode(mod->ctx, node, argname);
7515 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007516 return EXIT_FAILURE;
7517 }
Radek Krejci56c80412017-02-09 10:44:16 +01007518 } else {
7519 str[c] = lyxml_get_attr(node, argname, NULL);
7520 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007521 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007522 return EXIT_FAILURE;
7523 } else {
7524 str[c] = lydict_insert(mod->ctx, str[c], 0);
7525 }
7526
7527 if (stmt == LY_STMT_BELONGSTO) {
7528 /* get the belongs-to's mandatory prefix substatement */
7529 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007530 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007531 return EXIT_FAILURE;
7532 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007533 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007534 return EXIT_FAILURE;
7535 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007536 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007537 return EXIT_FAILURE;
7538 }
7539 /* and now finally get the value */
7540 if (p) {
7541 str = p[1];
7542 } else {
7543 str++;
7544 }
7545 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7546 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007547 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007548 return EXIT_FAILURE;
7549 }
7550 str[c] = lydict_insert(mod->ctx, str[c], 0);
7551
PavolVican6d400872017-03-01 15:19:18 +01007552 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 +01007553 return EXIT_FAILURE;
7554 }
PavolVican99c70722017-02-18 17:25:52 +01007555 } else if (stmt == LY_STMT_ARGUMENT) {
7556 str = (p) ? p[1] : str + 1;
7557 if (!node->child) {
7558 /* default value of yin element */
7559 ((uint8_t *)str)[c] = 2;
7560 } else {
7561 /* get optional yin-element substatement */
7562 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007563 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007564 return EXIT_FAILURE;
7565 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007566 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007567 return EXIT_FAILURE;
7568 } else {
7569 /* and now finally get the value */
7570 value = lyxml_get_attr(node->child, "value", NULL);
7571 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007572 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007573 return EXIT_FAILURE;
7574 }
7575 if (ly_strequal(value, "true", 0)) {
7576 ((uint8_t *)str)[c] = 1;
7577 } else if (ly_strequal(value, "false", 0)) {
7578 ((uint8_t *)str)[c] = 2;
7579 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007580 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007581 return EXIT_FAILURE;
7582 }
7583
7584 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7585 return EXIT_FAILURE;
7586 }
7587 }
7588 }
Radek Krejci56c80412017-02-09 10:44:16 +01007589 }
7590 }
7591 if (p) {
7592 /* enlarge the array(s) */
7593 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7594 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007595 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007596 lydict_remove(mod->ctx, p[0][c]);
7597 p[0][c] = NULL;
7598 return EXIT_FAILURE;
7599 }
7600 p[0] = reallocated;
7601 p[0][c + 1] = NULL;
7602
7603 if (stmt == LY_STMT_BELONGSTO) {
7604 /* enlarge the second belongs-to's array with prefixes */
7605 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7606 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007607 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007608 lydict_remove(mod->ctx, p[1][c]);
7609 p[1][c] = NULL;
7610 return EXIT_FAILURE;
7611 }
7612 p[1] = reallocated;
7613 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007614 } else if (stmt == LY_STMT_ARGUMENT){
7615 /* enlarge the second argument's array with yin element */
7616 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7617 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007618 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007619 ((uint8_t *)p[1])[c] = 0;
7620 return EXIT_FAILURE;
7621 }
7622 p[1] = reallocated;
7623 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007624 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007625 }
7626
7627 return EXIT_SUCCESS;
7628}
7629
7630static void *
7631yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7632 uint16_t mask)
7633{
7634 void *data;
7635 struct lyext_substmt *info;
7636
7637 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7638 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007639 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007640 return NULL;
7641 }
7642 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007643 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007644 return NULL;
7645 }
7646
7647 return data;
7648}
7649
Radek Krejcic1885952017-02-07 09:37:51 +01007650static int
7651yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007652 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007653 const char *val1_str, const char *val2_str, uint16_t mask,
7654 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7655{
7656 uint16_t *val;
7657 const char *str;
7658
7659 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7660 if (!val) {
7661 return EXIT_FAILURE;
7662 }
7663
7664 str = lyxml_get_attr(node, "value", NULL);
7665 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007666 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007667 } else if (!strcmp(val1_str, str)) {
7668 *val = *val | val1;
7669 } else if (!strcmp(val2_str, str)) {
7670 *val = *val | val2;
7671 } else {
7672 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007673 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007674 return EXIT_FAILURE;
7675 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007676 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007677 return EXIT_FAILURE;
7678 }
7679 return EXIT_SUCCESS;
7680}
7681
Radek Krejcif95b6292017-02-13 15:57:37 +01007682static struct lys_node **
7683yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7684{
7685 struct lyext_substmt *info;
7686 struct lys_node **snode, *siter;
7687
7688 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7689 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007690 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007691 return NULL;
7692 }
7693 if (info->cardinality < LY_STMT_CARD_SOME) {
7694 LY_TREE_FOR(*snode, siter) {
7695 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007696 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007697 return NULL;
7698 }
7699 }
7700 }
7701
7702 return snode;
7703}
7704
Radek Krejci8d6b7422017-02-03 14:42:13 +01007705static void **
7706yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7707{
7708 int c;
7709 void **data, ***p = NULL;
7710 void *reallocated;
7711 struct lyext_substmt *info;
7712
7713 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7714 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007715 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007716 return NULL;
7717 }
7718 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007719 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007720 return NULL;
7721 }
7722
7723 c = 0;
7724 if (info->cardinality >= LY_STMT_CARD_SOME) {
7725 /* there can be multiple instances, so instead of pointer to array,
7726 * we have in data pointer to pointer to array */
7727 p = (void ***)data;
7728 data = *p;
7729 if (!data) {
7730 /* allocate initial array */
7731 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007732 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007733 } else {
7734 for (c = 0; *data; data++, c++);
7735 }
7736 }
7737
7738 if (p) {
7739 /* enlarge the array */
7740 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007741 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007742 *p = reallocated;
7743 data = *p;
7744 data[c + 1] = NULL;
7745 }
7746
7747 return &data[c];
7748}
7749
7750int
7751lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7752 struct unres_schema *unres)
7753{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007754 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007755 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007756 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007757 const char *value, *name;
7758 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007759 struct lyext_substmt *info;
7760 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007761 long long int ll;
7762 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007763 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007764
Radek Krejcia8d111f2017-05-31 13:57:37 +02007765#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7766 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007767 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007768 (**(TYPE **)TO) = (TYPE)FROM;
7769
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007770#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007771 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7772 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007773 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007774 goto error; \
7775 } \
7776 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007777 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007778 goto error; \
7779 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007780 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007781 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7782 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007783 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007784 if (!(*pp)) { \
7785 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007786 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007787 } else { \
7788 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7789 } \
7790 p = &(*(TYPE**)pp)[i]; \
7791 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007792#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007793 if (pp) { \
7794 /* enlarge the array */ \
7795 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007796 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007797 *pp = reallocated; \
7798 (*(TYPE**)pp)[i + 1] = 0; \
7799 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007800#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7801 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7802 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007803 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007804#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7805 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007806 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007807 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007808 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007809 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7810 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7811 goto error; \
7812 } \
7813 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007814
Radek Krejci8d6b7422017-02-03 14:42:13 +01007815 LY_TREE_FOR_SAFE(yin->child, next, node) {
7816 if (!node->ns) {
7817 /* garbage */
7818 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7819 /* we have the extension's argument */
7820 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007821 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007822 goto error;
7823 }
7824 ext->arg_value = node->content;
7825 node->content = NULL;
7826 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7827 /* extension */
7828 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7829 goto error;
7830 }
7831 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007832 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007833 goto error;
7834 }
7835 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007836 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007837 goto error;
7838 }
7839 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007840 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007841 goto error;
7842 }
7843 } else if (!strcmp(node->name, "type")) {
7844 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7845 if (!type) {
7846 goto error;
7847 }
7848 /* allocate type structure */
7849 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007850 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007851
7852 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007853 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007854 (*type)->der = (struct lys_tpdf *)node;
7855 (*type)->parent = (struct lys_tpdf *)ext;
7856
7857 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7858 (*type)->der = NULL;
7859 goto error;
7860 }
7861 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007862 } else if (!strcmp(node->name, "typedef")) {
7863 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7864 if (!pp) {
7865 goto error;
7866 }
7867 /* allocate typedef structure */
7868 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007869 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007870
7871 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7872 goto error;
7873 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007874 } else if (!strcmp(node->name, "if-feature")) {
7875 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7876 if (!pp) {
7877 goto error;
7878 }
7879 /* allocate iffeature structure */
7880 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007881 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007882
7883 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7884 goto error;
7885 }
7886 } else if (!strcmp(node->name, "status")) {
7887 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7888 if (!p) {
7889 goto error;
7890 }
7891
Michal Vasko53b7da02018-02-13 15:28:42 +01007892 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007893 if (!strcmp(value, "current")) {
7894 *(uint16_t*)p |= LYS_STATUS_CURR;
7895 } else if (!strcmp(value, "deprecated")) {
7896 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7897 } else if (!strcmp(value, "obsolete")) {
7898 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7899 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007900 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007901 goto error;
7902 }
7903
7904 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7905 goto error;
7906 }
Radek Krejcic1885952017-02-07 09:37:51 +01007907 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007908 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007909 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007910 goto error;
7911 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007912 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007913 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007914 goto error;
7915 }
7916 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007917 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007918 goto error;
7919 }
Radek Krejcic1885952017-02-07 09:37:51 +01007920 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007921 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007922 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7923 goto error;
7924 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007925 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007926 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007927 goto error;
7928 }
7929 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007930 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007931 goto error;
7932 }
7933 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007934 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007935 goto error;
7936 }
7937 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007938 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007939 goto error;
7940 }
7941 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007942 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007943 goto error;
7944 }
7945 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007946 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007947 goto error;
7948 }
7949 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007950 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007951 goto error;
7952 }
7953 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007954 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007955 goto error;
7956 }
Radek Krejcic1885952017-02-07 09:37:51 +01007957 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007958 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7959 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007960 goto error;
7961 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007962 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007963 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007964 goto error;
7965 }
7966 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007967 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007968 goto error;
7969 }
7970 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007971 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007972 goto error;
7973 }
7974 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007975 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007976 goto error;
7977 }
Radek Krejcic1885952017-02-07 09:37:51 +01007978 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007979 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007980 goto error;
7981 }
7982 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007983 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007984 goto error;
7985 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007986 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007987 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007988
Michal Vasko53b7da02018-02-13 15:28:42 +01007989 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007990 v = strtol(value, NULL, 10);
7991
7992 /* range check */
7993 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007994 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007995 goto error;
7996 }
7997
7998 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7999 goto error;
8000 }
8001
8002 /* store the value */
8003 (*(uint8_t *)p) = (uint8_t)v;
8004
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008005 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008006 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008007 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008008
Michal Vasko53b7da02018-02-13 15:28:42 +01008009 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008010 while (isspace(value[0])) {
8011 value++;
8012 }
8013
8014 if (!strcmp(value, "unbounded")) {
8015 u = 0;
8016 } else {
8017 /* convert it to uint32_t */
8018 errno = 0; endptr = NULL;
8019 u = strtoul(value, &endptr, 10);
8020 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008021 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008022 goto error;
8023 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008024 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008025
8026 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8027 goto error;
8028 }
8029
8030 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008031 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008032
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008033 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008034 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008035 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008036
Michal Vasko53b7da02018-02-13 15:28:42 +01008037 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008038 while (isspace(value[0])) {
8039 value++;
8040 }
8041
8042 /* convert it to uint32_t */
8043 errno = 0;
8044 endptr = NULL;
8045 u = strtoul(value, &endptr, 10);
8046 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008047 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008048 goto error;
8049 }
8050
8051 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8052 goto error;
8053 }
8054
8055 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008056 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008057
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008058 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008059 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008060 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8061
Michal Vasko53b7da02018-02-13 15:28:42 +01008062 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008063 while (isspace(value[0])) {
8064 value++;
8065 }
8066
8067 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008068 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008069
8070 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008071 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008072 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008073 goto error;
8074 }
8075
8076 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8077 goto error;
8078 }
8079
8080 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008081 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008082
8083 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008084 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008085 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008086
Michal Vasko53b7da02018-02-13 15:28:42 +01008087 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008088 ll = strtoll(value, NULL, 10);
8089
8090 /* range check */
8091 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008092 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008093 goto error;
8094 }
8095
8096 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8097 goto error;
8098 }
8099
8100 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008101 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008102
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008103 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008104 } else if (!strcmp(node->name, "module")) {
8105 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8106 if (!pp) {
8107 goto error;
8108 }
8109
8110 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8111 if (!(*pp)) {
8112 goto error;
8113 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008114 } else if (!strcmp(node->name, "when")) {
8115 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8116
8117 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8118 if (!*(struct lys_when**)p) {
8119 goto error;
8120 }
8121
8122 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008123 } else if (!strcmp(node->name, "revision")) {
8124 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8125
8126 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008127 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008128 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8129 goto error;
8130 }
8131
8132 /* check uniqueness of the revision dates - not required by RFC */
8133 if (pp) {
8134 for (j = 0; j < i; j++) {
8135 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008136 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008137 }
8138 }
8139 }
8140
8141 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008142 } else if (!strcmp(node->name, "unique")) {
8143 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8144
8145 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008146 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008147 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8148 goto error;
8149 }
8150
8151 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8152 goto error;
8153 }
8154 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008155 } else if (!strcmp(node->name, "action")) {
8156 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8157 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008158 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008159 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008160 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008161 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008162 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008163 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008164 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008165 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008166 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008167 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008168 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008169 } else if (!strcmp(node->name, "output")) {
8170 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8171 } else if (!strcmp(node->name, "input")) {
8172 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8173 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008174 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008175 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008176 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008177 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008178 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008179 } else if (!strcmp(node->name, "notification")) {
8180 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8181 } else if (!strcmp(node->name, "uses")) {
8182 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008183 } else if (!strcmp(node->name, "length")) {
8184 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8185 } else if (!strcmp(node->name, "must")) {
8186 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8187 if (!pp) {
8188 goto error;
8189 }
8190 /* allocate structure for must */
8191 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008192 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008193
8194 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8195 goto error;
8196 }
8197 } else if (!strcmp(node->name, "pattern")) {
8198 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008199 GETVAL(mod->ctx, value, node, "value");
8200 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008201 goto error;
8202 }
8203
8204 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008205 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008206 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
8207
8208 modifier = 0x06; /* ACK */
8209 if (mod->version >= 2) {
8210 name = NULL;
8211 LY_TREE_FOR(node->child, child) {
8212 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8213 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008214 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008215 goto error;
8216 }
8217
Michal Vasko53b7da02018-02-13 15:28:42 +01008218 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008219 if (!strcmp(name, "invert-match")) {
8220 modifier = 0x15; /* NACK */
8221 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008222 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008223 goto error;
8224 }
8225 /* get extensions of the modifier */
8226 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8227 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8228 goto error;
8229 }
8230 }
8231 }
8232 }
8233
8234 /* store the value: modifier byte + value + terminating NULL byte */
8235 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008236 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008237 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8238 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8239 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8240
8241 /* get possible sub-statements */
8242 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8243 goto error;
8244 }
8245
8246 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8247 } else if (!strcmp(node->name, "range")) {
8248 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008249 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008250 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008251 }
8252 lyxml_free(mod->ctx, node);
8253 }
8254
PavolVicanc4b798e2017-02-20 23:15:27 +01008255 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8256 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008257 }
8258
Radek Krejci8d6b7422017-02-03 14:42:13 +01008259 return EXIT_SUCCESS;
8260
8261error:
8262 return EXIT_FAILURE;
8263}