blob: 9fccc6e2f9f9c48550ad42281939a72c171e4ecf [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,
Michal Vaskoa310a452018-11-21 12:34:29 +010094 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;
Michal Vaskoa310a452018-11-21 12:34:29 +0100144 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) {
Michal Vaskoc4405722019-03-14 09:17:34 +0100251 if (!child->ns) {
252 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Extension instance \"%s\" is missing namespace.", child->name);
253 return EXIT_FAILURE;
254 }
Radek Krejci07d0fb92017-01-13 14:11:05 +0100255 if (!strcmp(child->ns->value, LY_NSYIN)) {
256 /* skip the regular YIN nodes */
257 continue;
258 }
259
260 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100261parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100262
Michal Vasko53b7da02018-02-13 15:28:42 +0100263 YIN_CHECK_ARRAY_OVERFLOW_RETURN(mod->ctx, *ext_size, *ext_size, "extension", statement, EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100264 /* first, allocate a space for the extension instance in the parent elem */
265 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100266 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100267 (*ext) = reallocated;
268
269 /* init memory */
270 (*ext)[(*ext_size)] = NULL;
271
272 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100273 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100274 (*ext_size)++;
275 if (r) {
276 return EXIT_FAILURE;
277 }
278
Radek Krejcifccd1442017-01-16 10:26:57 +0100279 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100280 }
281
Radek Krejcie534c132016-11-23 13:32:31 +0100282 return EXIT_SUCCESS;
283}
284
Michal Vasko0d343d12015-08-24 14:57:36 +0200285/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200286static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200287fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
288 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100289{
Radek Krejci5323b492017-01-16 15:40:11 +0100290 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100291 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100292 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100293 struct ly_ctx *ctx = parent->module->ctx;
Michal Vasko1d337e12016-02-15 12:32:04 +0100294
Michal Vasko53b7da02018-02-13 15:28:42 +0100295 GETVAL(ctx, value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200296
297 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100298 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200299error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100300 return EXIT_FAILURE;
301 }
302
Michal Vasko56d082c2016-10-25 14:00:42 +0200303 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100304 return EXIT_FAILURE;
305 }
306
Radek Krejci9de2c042016-10-19 16:53:06 +0200307 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko53b7da02018-02-13 15:28:42 +0100308 lydict_remove(ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200309 if (r) {
310 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100311 }
312
Radek Krejci5323b492017-01-16 15:40:11 +0100313 LY_TREE_FOR_SAFE(yin->child, next, node) {
314 if (!node->ns) {
315 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100316 lyxml_free(ctx, node);
Radek Krejci5323b492017-01-16 15:40:11 +0100317 } else if (strcmp(node->ns->value, LY_NSYIN)) {
318 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100319 YIN_CHECK_ARRAY_OVERFLOW_RETURN(ctx, c_ext, iffeat->ext_size, "extensions", "if-feature", EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100320 c_ext++;
321 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100322 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
Radek Krejci5323b492017-01-16 15:40:11 +0100323 return EXIT_FAILURE;
324 }
325 }
326 if (c_ext) {
327 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100328 LY_CHECK_ERR_RETURN(!iffeat->ext, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100329 LY_TREE_FOR_SAFE(yin->child, next, node) {
330 /* extensions */
331 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100332 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100333 iffeat->ext_size++;
334 if (r) {
335 return EXIT_FAILURE;
336 }
337 }
338 }
339
Radek Krejci9ff0a922016-07-14 13:08:05 +0200340 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100341}
342
343/* logs directly */
344static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200345fill_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 +0200346{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200347 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100348 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200349 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200350 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100351 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100352 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200353
Michal Vasko53b7da02018-02-13 15:28:42 +0100354 GETVAL(ctx, value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100355 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200356
Radek Krejci07d0fb92017-01-13 14:11:05 +0100357 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100358 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200359 }
Radek Krejci04581c62015-05-22 21:24:00 +0200360
Pavol Vicand6cda452016-07-13 15:08:29 +0200361 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100362 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200363 }
364
Radek Krejcie534c132016-11-23 13:32:31 +0100365 LY_TREE_FOR(yin->child, node) {
366 if (strcmp(node->ns->value, LY_NSYIN)) {
367 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100368 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ident->ext_size, "extensions", "identity", error);
Radek Krejcie534c132016-11-23 13:32:31 +0100369 c_ext++;
370 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200371 if (c_base && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100372 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100373 goto error;
374 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100375 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_base, ident->base_size, "bases", "identity", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +0100376 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 +0100377 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200378 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200379 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100380
Radek Krejci018f1f52016-08-03 16:01:20 +0200381 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100382 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, ident->iffeature_size, "if-features", "identity", error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200383 c_ftrs++;
384
385 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100386 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100387 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200388 }
389 }
390
391 if (c_base) {
392 ident->base_size = 0;
393 ident->base = calloc(c_base, sizeof *ident->base);
Michal Vasko53b7da02018-02-13 15:28:42 +0100394 LY_CHECK_ERR_GOTO(!ident->base, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200395 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200396 if (c_ftrs) {
397 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +0100398 LY_CHECK_ERR_GOTO(!ident->iffeature, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200399 }
Radek Krejcie534c132016-11-23 13:32:31 +0100400 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100401 /* some extensions may be already present from the substatements */
402 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100403 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci18a44882017-01-23 13:47:29 +0100404 ident->ext = reallocated;
405
406 /* init memory */
407 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100408 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200409
Radek Krejcie534c132016-11-23 13:32:31 +0100410 LY_TREE_FOR_SAFE(yin->child, next, node) {
411 if (strcmp(node->ns->value, LY_NSYIN)) {
412 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100413 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 +0100414 ident->ext_size++;
415 if (rc) {
416 goto error;
417 }
418 } else if (!strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100419 GETVAL(ctx, value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100420 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100421 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100422 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200423 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100424
Radek Krejci48464ed2016-03-17 15:44:09 +0100425 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100426 lydict_remove(ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100427 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100428 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100429 lydict_remove(ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200430 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200431 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200432 ident->iffeature_size++;
433 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100434 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200435 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200436 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200437 }
Radek Krejci04581c62015-05-22 21:24:00 +0200438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200439 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200440
441error:
442 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200443}
444
Michal Vasko0d343d12015-08-24 14:57:36 +0200445/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200446static int
Radek Krejciaa9c5202017-02-15 16:10:14 +0100447read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
Radek Krejcifccd1442017-01-16 10:26:57 +0100448 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200449{
Radek Krejcifccd1442017-01-16 10:26:57 +0100450 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200451 const char *value;
Michal Vasko53b7da02018-02-13 15:28:42 +0100452 struct ly_ctx *ctx = module->ctx;
Radek Krejci41726f92015-06-19 13:11:05 +0200453
Radek Krejcifccd1442017-01-16 10:26:57 +0100454 LY_TREE_FOR_SAFE(yin->child, next, child) {
455 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200456 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200457 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100458 } else if (strcmp(child->ns->value, LY_NSYIN)) {
459 /* extension */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100460 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100461 return EXIT_FAILURE;
462 }
463 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200464 if (restr->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100465 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200466 return EXIT_FAILURE;
467 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100468 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100469 return EXIT_FAILURE;
470 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100471 restr->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200472 if (!restr->dsc) {
473 return EXIT_FAILURE;
474 }
475 } else if (!strcmp(child->name, "reference")) {
476 if (restr->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100477 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200478 return EXIT_FAILURE;
479 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100480 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100481 return EXIT_FAILURE;
482 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100483 restr->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200484 if (!restr->ref) {
485 return EXIT_FAILURE;
486 }
487 } else if (!strcmp(child->name, "error-app-tag")) {
488 if (restr->eapptag) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100489 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200490 return EXIT_FAILURE;
491 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100492 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100493 return EXIT_FAILURE;
494 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100495 GETVAL(ctx, value, child, "value");
496 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200497 } else if (!strcmp(child->name, "error-message")) {
498 if (restr->emsg) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100499 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200500 return EXIT_FAILURE;
501 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100502 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100503 return EXIT_FAILURE;
504 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100505 restr->emsg = read_yin_subnode(ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200506 if (!restr->emsg) {
507 return EXIT_FAILURE;
508 }
509 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100510 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200511 return EXIT_FAILURE;
512 }
Radek Krejci41726f92015-06-19 13:11:05 +0200513 }
514
515 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200516
517error:
518 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200519}
520
Michal Vasko88c29542015-11-27 14:57:53 +0100521/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
522int
Radek Krejcib8048692015-08-05 13:36:34 +0200523fill_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 +0100524 int parenttype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200525{
Michal Vasko568b1952018-01-30 15:53:30 +0100526 const char *value, *name, *module_name = NULL;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200527 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100528 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100529 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200530 struct lys_type_bit bit, *bits_sc = NULL;
531 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200532 struct lys_type *dertype;
Michal Vasko53b7da02018-02-13 15:28:42 +0100533 struct ly_ctx *ctx = module->ctx;
Radek Krejcidce5f972017-09-12 15:47:49 +0200534 int rc, val_set, c_ftrs, c_ext = 0;
535 unsigned int i, j;
Radek Krejcidc008d72016-02-17 13:12:14 +0100536 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200537 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200538 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200539 size_t len;
Radek Krejcib53154b2017-07-19 09:14:13 +0200540 int in_grp = 0;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200541 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200542
Radek Krejcie534c132016-11-23 13:32:31 +0100543 /* init */
544 memset(&exts, 0, sizeof exts);
545
Michal Vasko53b7da02018-02-13 15:28:42 +0100546 GETVAL(ctx, value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100547 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200548 if (!value) {
549 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200550 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200551
552 i = parse_identifier(value);
553 if (i < 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100554 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
555 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200556 goto error;
557 }
558 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100559 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200560 if (value[i]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100561 module_name = lydict_insert(ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100562 name += i;
563 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100564 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
565 lydict_remove(ctx, module_name);
566 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200567 goto error;
568 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200569 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100570 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200571 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200572
Michal Vasko568b1952018-01-30 15:53:30 +0100573 rc = resolve_superior_type(name, module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200574 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100575 LOGVAL(ctx, LYE_INMOD, LY_VLOG_NONE, NULL, module_name);
576 lydict_remove(ctx, module_name);
577 lydict_remove(ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200578 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100579
580 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200581 } else if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100582 LOGVAL(ctx, LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
583 lydict_remove(ctx, module_name);
584 lydict_remove(ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100585 ret = EXIT_FAILURE;
586 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100588 lydict_remove(ctx, module_name);
589 lydict_remove(ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200590
Michal Vasko101658e2018-06-05 15:05:54 +0200591 if (type->value_flags & LY_VALUE_UNRESGRP) {
Radek Krejcic13db382016-08-16 10:52:42 +0200592 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Michal Vasko70bf8e52018-03-26 11:32:33 +0200593 * unresolved item left inside the grouping, LYTYPE_GRP used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200594 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
595 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200596 assert(((struct lys_node_grp *)siter)->unres_count);
597 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200598 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100599 LOGINT(ctx);
Radek Krejcic13db382016-08-16 10:52:42 +0200600 goto error;
601 }
Michal Vasko101658e2018-06-05 15:05:54 +0200602 type->value_flags &= ~LY_VALUE_UNRESGRP;
Radek Krejcic13db382016-08-16 10:52:42 +0200603 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200604 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200605
Radek Krejcicf509982015-12-15 09:22:44 +0100606 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100607 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Michal Vasko53b7da02018-02-13 15:28:42 +0100608 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100609 return -1;
610 }
611
Radek Krejcie534c132016-11-23 13:32:31 +0100612 /* parse extension instances */
613 LY_TREE_FOR_SAFE(yin->child, next, node) {
614 if (!node->ns) {
615 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100616 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100617 continue;
618 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
619 /* YANG (YIN) statements - process later */
620 continue;
621 }
622
Michal Vasko53b7da02018-02-13 15:28:42 +0100623 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, type->ext_size, "extensions", "type", error);
Radek Krejcidce5f972017-09-12 15:47:49 +0200624
Michal Vasko53b7da02018-02-13 15:28:42 +0100625 lyxml_unlink_elem(ctx, node, 2);
626 lyxml_add_child(ctx, &exts, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100627 c_ext++;
628 }
629 if (c_ext) {
630 type->ext = calloc(c_ext, sizeof *type->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100631 LY_CHECK_ERR_GOTO(!type->ext, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200632
Radek Krejcie534c132016-11-23 13:32:31 +0100633 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100634 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 +0100635 type->ext_size++;
636 if (rc) {
637 goto error;
638 }
639 }
640 }
641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200643 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200644 /* RFC 6020 9.7.4 - bit */
645
646 /* get bit specifications, at least one must be present */
647 LY_TREE_FOR_SAFE(yin->child, next, node) {
648 if (!strcmp(node->name, "bit")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100649 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.bits.count, type->info.bits.count, "bits", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200650 type->info.bits.count = 0; goto error);
Radek Krejci994b6f62015-06-18 16:47:27 +0200651 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200652 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100653 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200654 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200655 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200656 }
657 }
Radek Krejcie663e012016-08-01 17:12:34 +0200658 dertype = &type->der->type;
659 if (!dertype->der) {
660 if (!type->info.bits.count) {
661 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100662 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200663 goto error;
664 }
665 } else {
666 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
667 if (module->version < 2 && type->info.bits.count) {
668 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
669 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100670 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200671 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200672 goto error;
673 }
Radek Krejciac781922015-07-09 15:35:14 +0200674 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200675
676 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +0100677 LY_CHECK_ERR_GOTO(!type->info.bits.bit, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200678
Radek Krejci73adb602015-07-02 18:07:40 +0200679 p = 0;
Michal Vaskoc643f712018-09-14 08:26:13 +0200680 i = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200681 LY_TREE_FOR(yin->child, next) {
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200682 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200683
Michal Vasko53b7da02018-02-13 15:28:42 +0100684 GETVAL(ctx, value, next, "name");
685 if (lyp_check_identifier(ctx, value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100686 goto error;
687 }
688
Michal Vasko53b7da02018-02-13 15:28:42 +0100689 type->info.bits.bit[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100690 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 +0200691 type->info.bits.count = i + 1;
692 goto error;
693 }
694
Radek Krejcie663e012016-08-01 17:12:34 +0200695 if (!dertype->der) { /* directly derived type from bits built-in type */
696 /* check the name uniqueness */
697 for (j = 0; j < i; j++) {
698 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100699 LOGVAL(ctx, LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejcie663e012016-08-01 17:12:34 +0200700 type->info.bits.count = i + 1;
701 goto error;
702 }
703 }
704 } else {
705 /* restricted bits type - the name MUST be used in the base type */
706 bits_sc = dertype->info.bits.bit;
707 for (j = 0; j < dertype->info.bits.count; j++) {
708 if (ly_strequal(bits_sc[j].name, value, 1)) {
709 break;
710 }
711 }
712 if (j == dertype->info.bits.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100713 LOGVAL(ctx, LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200714 type->info.bits.count = i + 1;
715 goto error;
716 }
717 }
718
Radek Krejcie663e012016-08-01 17:12:34 +0200719
Radek Krejci0d70c372015-07-02 16:23:10 +0200720 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100721 LY_TREE_FOR_SAFE(next->child, next2, node) {
722 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200723 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200724 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100725 } else if (strcmp(node->ns->value, LY_NSYIN)) {
726 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100727 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Michal Vasko53b7da02018-02-13 15:28:42 +0100728 LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci9b15fea2017-01-23 11:31:43 +0100729 goto error;
730 }
731 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200732 if (p_ != -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100733 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +0200734 type->info.bits.count = i + 1;
735 goto error;
736 }
737
Michal Vasko53b7da02018-02-13 15:28:42 +0100738 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200739 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200740
741 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200742 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100743 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200744 type->info.bits.count = i + 1;
745 goto error;
746 }
747 type->info.bits.bit[i].pos = (uint32_t)p_;
748
Radek Krejcie663e012016-08-01 17:12:34 +0200749 if (!dertype->der) { /* directly derived type from bits built-in type */
750 /* keep the highest enum value for automatic increment */
751 if (type->info.bits.bit[i].pos >= p) {
752 p = type->info.bits.bit[i].pos;
753 p++;
754 } else {
755 /* check that the value is unique */
756 for (j = 0; j < i; j++) {
757 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100758 LOGVAL(ctx, LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +0200759 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
760 type->info.bits.bit[j].name);
761 type->info.bits.count = i + 1;
762 goto error;
763 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200764 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200765 }
766 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200767
Radek Krejci8d6b7422017-02-03 14:42:13 +0100768 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100769 LYEXT_SUBSTMT_POSITION, 0, unres)) {
770 goto error;
771 }
PavolVican92f23622017-12-12 13:35:56 +0100772
PavolVican0144fae2018-02-05 15:54:17 +0100773 for (j = 0; j < type->info.bits.bit[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100774 /* set flag, which represent LYEXT_OPT_VALID */
775 if (type->info.bits.bit[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100776 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100777 break;
778 }
779 }
780
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200781 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100782 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 +0200783 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200784 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100785 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200786 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200787 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200788 }
Radek Krejcie663e012016-08-01 17:12:34 +0200789
790 if (!dertype->der) { /* directly derived type from bits built-in type */
791 if (p_ == -1) {
792 /* assign value automatically */
793 if (p > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100794 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejcie663e012016-08-01 17:12:34 +0200795 type->info.bits.count = i + 1;
796 goto error;
797 }
798 type->info.bits.bit[i].pos = (uint32_t)p;
799 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
800 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200801 }
Radek Krejcie663e012016-08-01 17:12:34 +0200802 } else { /* restricted bits type */
803 if (p_ == -1) {
804 /* automatically assign position from base type */
805 type->info.bits.bit[i].pos = bits_sc[j].pos;
806 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
807 } else {
808 /* check that the assigned position corresponds to the original
809 * position of the bit in the base type */
810 if (p_ != bits_sc[j].pos) {
811 /* p_ - assigned position in restricted bits
812 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100813 LOGVAL(ctx, LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200814 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200815 type->info.bits.count = i + 1;
816 goto error;
817 }
818 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200819 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200820
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200821 /* if-features */
822 if (c_ftrs) {
823 bits_sc = &type->info.bits.bit[i];
824 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
825 if (!bits_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100826 LOGMEM(ctx);
Radek Krejci994b6f62015-06-18 16:47:27 +0200827 type->info.bits.count = i + 1;
828 goto error;
829 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200830
831 LY_TREE_FOR(next->child, node) {
832 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200833 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200834 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
835 bits_sc->iffeature_size++;
836 if (rc) {
837 type->info.bits.count = i + 1;
838 goto error;
839 }
840 }
841 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200842 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200843
844 /* keep them ordered by position */
845 j = i;
846 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
847 /* switch them */
848 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
849 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
850 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
851 j--;
852 }
Michal Vaskoc643f712018-09-14 08:26:13 +0200853
854 ++i;
Radek Krejci994b6f62015-06-18 16:47:27 +0200855 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200856 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200859 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200860 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200861
Radek Krejcif9401c32015-06-26 16:47:36 +0200862 if (!strcmp(node->name, "range")) {
863 if (type->info.dec64.range) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100864 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200865 goto error;
866 }
867
Michal Vasko53b7da02018-02-13 15:28:42 +0100868 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200869 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko53b7da02018-02-13 15:28:42 +0100870 LY_CHECK_ERR_GOTO(!type->info.dec64.range, LOGMEM(ctx), error);
871 type->info.dec64.range->expr = lydict_insert(ctx, value, 0);
Radek Krejcif9401c32015-06-26 16:47:36 +0200872
873 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100874 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200875 goto error;
876 }
PavolVican0144fae2018-02-05 15:54:17 +0100877 for (j = 0; j < type->info.dec64.range->ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100878 /* set flag, which represent LYEXT_OPT_VALID */
879 if (type->info.dec64.range->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100880 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100881 break;
882 }
883 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200884 } else if (!strcmp(node->name, "fraction-digits")) {
885 if (type->info.dec64.dig) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100886 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200887 goto error;
888 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100889 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200890 v = strtol(value, NULL, 10);
891
892 /* range check */
893 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100894 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200895 goto error;
896 }
897 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200898 type->info.dec64.div = 10;
899 for (i = 1; i < v; i++) {
900 type->info.dec64.div *= 10;
901 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100902
903 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100904 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100905 goto error;
906 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200907 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100908 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200909 goto error;
910 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200911 }
912
913 /* mandatory sub-statement(s) check */
914 if (!type->info.dec64.dig && !type->der->type.der) {
915 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vasko53b7da02018-02-13 15:28:42 +0100916 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200917 goto error;
918 }
Radek Krejci7511f402015-07-10 09:56:30 +0200919 if (type->info.dec64.dig && type->der->type.der) {
920 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vasko53b7da02018-02-13 15:28:42 +0100921 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200922 goto error;
923 }
Radek Krejci4800f652016-09-08 14:02:52 +0200924
925 /* copy fraction-digits specification from parent type for easier internal use */
926 if (type->der->type.der) {
927 type->info.dec64.dig = type->der->type.info.dec64.dig;
928 type->info.dec64.div = type->der->type.info.dec64.div;
929 }
930
Michal Vasko53b7da02018-02-13 15:28:42 +0100931 if (type->info.dec64.range && lyp_check_length_range(ctx, type->info.dec64.range->expr, type)) {
932 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200933 goto error;
934 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200938 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200939
Radek Krejci994b6f62015-06-18 16:47:27 +0200940 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 if (!strcmp(node->name, "enum")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100944 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.enums.count, type->info.enums.count, "enums", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200945 type->info.enums.count = 0; goto error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200947 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100948 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200949 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200950 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 }
952 }
Radek Krejcie663e012016-08-01 17:12:34 +0200953 dertype = &type->der->type;
954 if (!dertype->der) {
955 if (!type->info.enums.count) {
956 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100957 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200958 goto error;
959 }
960 } else {
961 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
962 if (module->version < 2 && type->info.enums.count) {
963 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
964 * 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 +0100965 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200966 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200967 goto error;
968 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200969 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200970
Radek Krejci1574a8d2015-08-03 14:16:52 +0200971 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +0100972 LY_CHECK_ERR_GOTO(!type->info.enums.enm, LOGMEM(ctx), error);
Radek Krejcifc8d8322016-06-24 11:23:23 +0200973
Radek Krejcie663e012016-08-01 17:12:34 +0200974 v = 0;
Michal Vaskoc643f712018-09-14 08:26:13 +0200975 i = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200976 LY_TREE_FOR(yin->child, next) {
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200977 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200978
Michal Vasko53b7da02018-02-13 15:28:42 +0100979 GETVAL(ctx, value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100980 if (!value[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100981 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
982 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100983 goto error;
984 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100985 type->info.enums.enm[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100986 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 +0200987 type->info.enums.count = i + 1;
988 goto error;
989 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200992 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100994 LOGVAL(ctx, LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 type->info.enums.count = i + 1;
996 goto error;
997 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200998
Radek Krejcie663e012016-08-01 17:12:34 +0200999 if (!dertype->der) { /* directly derived type from enumeration built-in type */
1000 /* check the name uniqueness */
1001 for (j = 0; j < i; j++) {
1002 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001003 LOGVAL(ctx, LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
Radek Krejcie663e012016-08-01 17:12:34 +02001004 type->info.enums.count = i + 1;
1005 goto error;
1006 }
1007 }
1008 } else {
1009 /* restricted enumeration type - the name MUST be used in the base type */
1010 enms_sc = dertype->info.enums.enm;
1011 for (j = 0; j < dertype->info.enums.count; j++) {
1012 if (ly_strequal(enms_sc[j].name, value, 1)) {
1013 break;
1014 }
1015 }
1016 if (j == dertype->info.enums.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001017 LOGVAL(ctx, LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001018 type->info.enums.count = i + 1;
1019 goto error;
1020 }
1021 }
Radek Krejci04581c62015-05-22 21:24:00 +02001022
Radek Krejcie663e012016-08-01 17:12:34 +02001023 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001024 LY_TREE_FOR_SAFE(next->child, next2, node) {
1025 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001026 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001027 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001028 } else if (strcmp(node->ns->value, LY_NSYIN)) {
1029 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001030 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001031 LYEXT_SUBSTMT_SELF, 0, unres)) {
1032 goto error;
1033 }
1034 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +02001035 if (val_set) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001036 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +02001037 type->info.enums.count = i + 1;
1038 goto error;
1039 }
1040
Michal Vasko53b7da02018-02-13 15:28:42 +01001041 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +02001042 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +02001043
1044 /* range check */
1045 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001046 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +02001047 type->info.enums.count = i + 1;
1048 goto error;
1049 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001050 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +02001051
Radek Krejcie663e012016-08-01 17:12:34 +02001052 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001053 if (!i) {
1054 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001055 v = type->info.enums.enm[i].value;
1056 v++;
1057 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001058 /* keep the highest enum value for automatic increment */
1059 if (type->info.enums.enm[i].value >= v) {
1060 v = type->info.enums.enm[i].value;
1061 v++;
1062 } else {
1063 /* check that the value is unique */
1064 for (j = 0; j < i; j++) {
1065 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001066 LOGVAL(ctx, LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican5de389c2016-08-30 08:55:15 +02001067 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1068 type->info.enums.enm[j].name);
1069 type->info.enums.count = i + 1;
1070 goto error;
1071 }
Radek Krejcie663e012016-08-01 17:12:34 +02001072 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001073 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 }
1075 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001076 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001077
Radek Krejci8d6b7422017-02-03 14:42:13 +01001078 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001079 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1080 goto error;
1081 }
PavolVican92f23622017-12-12 13:35:56 +01001082
PavolVican0144fae2018-02-05 15:54:17 +01001083 for (j = 0; j < type->info.enums.enm[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +01001084 /* set flag, which represent LYEXT_OPT_VALID */
1085 if (type->info.enums.enm[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001086 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001087 break;
1088 }
1089 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001090 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001091 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 +02001092 c_ftrs++;
1093
Radek Krejci0d70c372015-07-02 16:23:10 +02001094 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001095 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001096 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001097 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001098 }
Radek Krejcie663e012016-08-01 17:12:34 +02001099
1100 if (!dertype->der) { /* directly derived type from enumeration */
1101 if (!val_set) {
1102 /* assign value automatically */
1103 if (v > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001104 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejcie663e012016-08-01 17:12:34 +02001105 type->info.enums.count = i + 1;
1106 goto error;
1107 }
1108 type->info.enums.enm[i].value = v;
1109 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1110 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001111 }
Radek Krejcie663e012016-08-01 17:12:34 +02001112 } else { /* restricted enum type */
1113 if (!val_set) {
1114 /* automatically assign value from base type */
1115 type->info.enums.enm[i].value = enms_sc[j].value;
1116 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1117 } else {
1118 /* check that the assigned value corresponds to the original
1119 * value of the enum in the base type */
1120 if (v_ != enms_sc[j].value) {
1121 /* v_ - assigned value in restricted enum
1122 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001123 LOGVAL(ctx, LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001124 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001125 type->info.enums.count = i + 1;
1126 goto error;
1127 }
1128 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001130
1131 /* if-features */
1132 if (c_ftrs) {
1133 enms_sc = &type->info.enums.enm[i];
1134 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1135 if (!enms_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001136 LOGMEM(ctx);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 type->info.enums.count = i + 1;
1138 goto error;
1139 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001140
1141 LY_TREE_FOR(next->child, node) {
1142 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001143 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001144 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1145 enms_sc->iffeature_size++;
1146 if (rc) {
1147 type->info.enums.count = i + 1;
1148 goto error;
1149 }
1150 }
1151 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001152 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001153
Michal Vaskoc643f712018-09-14 08:26:13 +02001154 ++i;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155 }
1156 break;
1157
1158 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001159 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001160
Michal Vaskof2d43962016-09-02 11:10:16 +02001161 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001162 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001163
Michal Vaskoe29c6622015-11-27 15:02:31 +01001164 if (strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001165 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001166 goto error;
1167 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001168
Michal Vasko53b7da02018-02-13 15:28:42 +01001169 GETVAL(ctx, value, yin->child, "name");
Michal Vaskof2d43962016-09-02 11:10:16 +02001170 /* store in the JSON format */
1171 value = transform_schema2json(module, value);
1172 if (!value) {
1173 goto error;
1174 }
1175 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Michal Vasko53b7da02018-02-13 15:28:42 +01001176 lydict_remove(ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001177 if (rc == -1) {
1178 goto error;
1179 }
Radek Krejci18a44882017-01-23 13:47:29 +01001180
Radek Krejci8d6b7422017-02-03 14:42:13 +01001181 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001182 goto error;
1183 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001184 }
1185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001187 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001188 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001189 break;
1190 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001191 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001192 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001193 } else {
1194 if (type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001195 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
Pavol Vicanf0046f42016-09-07 15:11:09 +02001196 goto error;
1197 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001199 if (yin->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001200 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001201 goto error;
1202 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001203 break;
1204
1205 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001206 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001207 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001208
Radek Krejciaf351422015-06-19 14:49:38 +02001209 if (!strcmp(node->name, "require-instance")) {
1210 if (type->info.inst.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001211 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001212 goto error;
1213 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001214 GETVAL(ctx, value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001215 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001216 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001217 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001218 type->info.inst.req = -1;
1219 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001220 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001221 goto error;
1222 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001223
1224 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001225 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001226 goto error;
1227 }
Radek Krejciaf351422015-06-19 14:49:38 +02001228 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001229 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001230 goto error;
1231 }
Radek Krejciaf351422015-06-19 14:49:38 +02001232 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 break;
1235
Radek Krejcif2860132015-06-20 12:37:20 +02001236 case LY_TYPE_BINARY:
1237 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 case LY_TYPE_INT8:
1239 case LY_TYPE_INT16:
1240 case LY_TYPE_INT32:
1241 case LY_TYPE_INT64:
1242 case LY_TYPE_UINT8:
1243 case LY_TYPE_UINT16:
1244 case LY_TYPE_UINT32:
1245 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001246 /* RFC 6020 9.2.4 - range */
1247
1248 /* length and range are actually the same restriction, so process
1249 * them by this common code, we just need to differ the name and
1250 * structure where the information will be stored
1251 */
1252 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001253 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001254 name = "length";
1255 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001256 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001257 name = "range";
1258 }
1259
Radek Krejci73adb602015-07-02 18:07:40 +02001260 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001261
Radek Krejcif2860132015-06-20 12:37:20 +02001262 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001263 if (*restrs) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001264 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001265 goto error;
1266 }
1267
Michal Vasko53b7da02018-02-13 15:28:42 +01001268 GETVAL(ctx, value, node, "value");
1269 if (lyp_check_length_range(ctx, value, type)) {
1270 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001271 goto error;
1272 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001273 *restrs = calloc(1, sizeof **restrs);
Michal Vasko53b7da02018-02-13 15:28:42 +01001274 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM(ctx), error);
1275 (*restrs)->expr = lydict_insert(ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001276
1277 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001278 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001279 goto error;
1280 }
PavolVican92f23622017-12-12 13:35:56 +01001281
1282 for (j = 0; j < (*restrs)->ext_size; ++j) {
1283 /* set flag, which represent LYEXT_OPT_VALID */
1284 if ((*restrs)->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001285 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001286 break;
1287 }
1288 }
Radek Krejcif2860132015-06-20 12:37:20 +02001289 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001290 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001291 goto error;
1292 }
Radek Krejcif2860132015-06-20 12:37:20 +02001293 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001294 break;
1295
1296 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001297 /* flag resolving for later use */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001298 if (!parenttype) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001299 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1300 if (siter) {
1301 /* just a flag - do not resolve */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001302 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001303 }
1304 }
1305
Radek Krejcidc4c1412015-06-19 15:39:54 +02001306 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001307 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001308
Michal Vasko88c29542015-11-27 14:57:53 +01001309 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001310 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001311 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001312 goto error;
1313 }
1314
Michal Vasko53b7da02018-02-13 15:28:42 +01001315 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001316 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001317 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001318 if (!type->info.lref.path) {
1319 goto error;
1320 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001321
1322 /* try to resolve leafref path only when this is instantiated
1323 * leaf, so it is not:
1324 * - typedef's type,
1325 * - in grouping definition,
1326 * - just instantiated in a grouping definition,
1327 * because in those cases the nodes referenced in path might not be present
1328 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001329 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001330 goto error;
1331 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001332
1333 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001334 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001335 goto error;
1336 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001337 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001338 if (type->info.lref.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001339 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001340 goto error;
1341 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001342 GETVAL(ctx, value, node, "value");
Michal Vasko08ae53e2016-09-02 12:40:04 +02001343 if (!strcmp(value, "true")) {
1344 type->info.lref.req = 1;
1345 } else if (!strcmp(value, "false")) {
1346 type->info.lref.req = -1;
1347 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001348 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001349 goto error;
1350 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001351
1352 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001353 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001354 goto error;
1355 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001356 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001357 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001358 goto error;
1359 }
Radek Krejci73adb602015-07-02 18:07:40 +02001360 }
1361
Radek Krejci742be352016-07-17 12:18:54 +02001362 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001363 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001364 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001365 goto error;
1366 } else {
1367 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001368 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001369 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001370 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001371 goto error;
1372 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001373 }
Radek Krejci742be352016-07-17 12:18:54 +02001374 }
1375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001376 break;
1377
1378 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001379 /* RFC 6020 9.4.4 - length */
1380 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001381 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001382 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001383
Radek Krejci3733a802015-06-19 13:43:21 +02001384 if (!strcmp(node->name, "length")) {
1385 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001386 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001387 goto error;
1388 }
1389
Michal Vasko53b7da02018-02-13 15:28:42 +01001390 GETVAL(ctx, value, node, "value");
1391 if (lyp_check_length_range(ctx, value, type)) {
1392 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001393 goto error;
1394 }
1395 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001396 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1397 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001398
Radek Krejci5fbc9162015-06-19 14:11:11 +02001399 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001400 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001401 goto error;
1402 }
PavolVican92f23622017-12-12 13:35:56 +01001403
1404 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1405 /* set flag, which represent LYEXT_OPT_VALID */
1406 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001407 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001408 break;
1409 }
1410 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001411 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001412 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001413 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001414 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001415 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001416 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001417 goto error;
1418 }
1419 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001420 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001421 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001422 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001423 in_grp = 1;
1424 }
Radek Krejci73adb602015-07-02 18:07:40 +02001425 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001426 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001427#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001428 if (!in_grp) {
1429 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001430 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001431 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001432 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001433#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001434 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001435 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001436
Michal Vasko9c7dee32018-07-09 09:12:59 +02001437 if (in_grp) {
1438 /* in grouping, just check the pattern syntax */
1439 if (!(ctx->models.flags & LY_CTX_TRUSTED) && lyp_check_pattern(ctx, value, NULL)) {
1440 goto error;
Radek Krejcib53154b2017-07-19 09:14:13 +02001441 }
Michal Vasko69068852015-07-13 14:34:31 +02001442 }
Michal Vasko9c7dee32018-07-09 09:12:59 +02001443#ifdef LY_ENABLED_CACHE
1444 else {
1445 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
1446 if (lyp_precompile_pattern(ctx, value,
1447 (pcre **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1448 (pcre_extra **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1449 goto error;
1450 }
1451 }
1452#endif
Radek Krejcifccd1442017-01-16 10:26:57 +01001453 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001454 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001455
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001456 modifier = 0x06; /* ACK */
1457 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001458 if (module->version >= 2) {
1459 LY_TREE_FOR_SAFE(node->child, next2, child) {
1460 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1461 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001462 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001463 goto error;
1464 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001465
Michal Vasko53b7da02018-02-13 15:28:42 +01001466 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001467 if (!strcmp(name, "invert-match")) {
1468 modifier = 0x15; /* NACK */
1469 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001470 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001471 goto error;
1472 }
1473 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001474 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001475 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1476 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001477 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001478
Michal Vasko53b7da02018-02-13 15:28:42 +01001479 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001480 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001481 }
1482 }
1483
1484 len = strlen(value);
1485 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001486 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001487 buf[0] = modifier;
1488 strcpy(&buf[1], value);
1489
Michal Vasko53b7da02018-02-13 15:28:42 +01001490 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001491
1492 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001493 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001494 goto error;
1495 }
PavolVican92f23622017-12-12 13:35:56 +01001496
1497 for (j = 0; j < restr->ext_size; ++j) {
1498 /* set flag, which represent LYEXT_OPT_VALID */
1499 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001500 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001501 break;
1502 }
1503 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001504 }
1505 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 break;
1507
1508 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001509 /* RFC 6020 7.4 - type */
1510 /* count number of types in union */
1511 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001512 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001513
Radek Krejcie4c366b2015-07-02 10:11:31 +02001514 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001515 if (type->der->type.der) {
1516 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001517 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001518 goto error;
1519 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001520 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001521 i++;
1522 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001523 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001524 goto error;
1525 }
1526 }
1527
Radek Krejci038d5d92016-09-12 15:07:15 +02001528 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001529 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001530 goto error;
1531 }
1532
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001533 /* inherit instid presence information */
1534 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1535 type->info.uni.has_ptr_type = 1;
1536 }
1537
Radek Krejcie4c366b2015-07-02 10:11:31 +02001538 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001539 if (i) {
1540 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001541 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001542 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001543
Radek Krejcie4c366b2015-07-02 10:11:31 +02001544 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001545 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001546 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001547 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001548 if (!rc) {
1549 type->info.uni.count++;
1550
Radek Krejci7de36cf2016-09-12 16:18:50 +02001551 if (module->version < 2) {
1552 /* union's type cannot be empty or leafref */
1553 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001554 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001555 rc = -1;
1556 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001557 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001558 rc = -1;
1559 }
Michal Vasko88c29542015-11-27 14:57:53 +01001560 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001561
1562 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001563 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1564 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1565 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001566 type->info.uni.has_ptr_type = 1;
1567 }
Michal Vasko88c29542015-11-27 14:57:53 +01001568 }
1569 if (rc) {
1570 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1571 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001572 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001573 }
1574 free(type->info.uni.types);
1575 type->info.uni.types = NULL;
1576 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001577 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001578 type->der = NULL;
1579 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001580
1581 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001582 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001583 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001584 goto error;
1585 }
Michal Vasko88c29542015-11-27 14:57:53 +01001586 }
1587 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001588
Michal Vasko88c29542015-11-27 14:57:53 +01001589 case LY_TYPE_BOOL:
1590 case LY_TYPE_EMPTY:
1591 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001592 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001593 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001594 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001596 break;
1597
1598 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001599 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001600 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 }
1602
PavolVican92f23622017-12-12 13:35:56 +01001603 for(j = 0; j < type->ext_size; ++j) {
1604 /* set flag, which represent LYEXT_OPT_VALID */
1605 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001606 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001607 break;
1608 }
1609 }
1610
1611 /* if derived type has extension, which need validate data */
1612 dertype = &type->der->type;
1613 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001614 if (dertype->parent->flags & LYS_VALID_EXT) {
1615 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001616 }
1617 dertype = &dertype->der->type;
1618 }
1619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001621
1622error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001623 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001624 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001625}
1626
Michal Vasko0d343d12015-08-24 14:57:36 +02001627/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001629fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1630 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001631{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001632 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001633 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001634 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001635 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001636 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001637
Michal Vasko53b7da02018-02-13 15:28:42 +01001638 GETVAL(ctx, value, yin, "name");
1639 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 goto error;
1641 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001642 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001645 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 goto error;
1647 }
Radek Krejcieac35532015-05-31 19:09:15 +02001648
Michal Vasko88c29542015-11-27 14:57:53 +01001649 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001650 if (strcmp(node->ns->value, LY_NSYIN)) {
1651 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001652 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001653 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001654 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001655 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001656 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001657 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 goto error;
1659 }
Michal Vasko88c29542015-11-27 14:57:53 +01001660 /* HACK for unres */
1661 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001662 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001663 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001664 goto error;
1665 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001666 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001667
Radek Krejci07d0fb92017-01-13 14:11:05 +01001668 /* 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 +01001669 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 } else if (!strcmp(node->name, "default")) {
1671 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001672 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001673 goto error;
1674 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001675 GETVAL(ctx, value, node, "value");
1676 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001677
Radek Krejci8d6b7422017-02-03 14:42:13 +01001678 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001679 goto error;
1680 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 } else if (!strcmp(node->name, "units")) {
1682 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001683 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001684 goto error;
1685 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001686 GETVAL(ctx, value, node, "name");
1687 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001688
Radek Krejci8d6b7422017-02-03 14:42:13 +01001689 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001690 goto error;
1691 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001693 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 goto error;
1695 }
Radek Krejcie534c132016-11-23 13:32:31 +01001696
Michal Vasko53b7da02018-02-13 15:28:42 +01001697 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001698 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001701 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001702 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 goto error;
1704 }
Radek Krejcieac35532015-05-31 19:09:15 +02001705
Michal Vasko478c4652016-07-21 12:55:01 +02001706 /* check default value (if not defined, there still could be some restrictions
1707 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001708 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001709 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001710 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001712
Radek Krejcie534c132016-11-23 13:32:31 +01001713 /* finish extensions parsing */
1714 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001715 /* some extensions may be already present from the substatements */
1716 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001717 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001718 tpdf->ext = reallocated;
1719
1720 /* init memory */
1721 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1722
Radek Krejcie534c132016-11-23 13:32:31 +01001723 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001724 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 +01001725 tpdf->ext_size++;
1726 if (rc) {
1727 goto error;
1728 }
1729 }
1730 }
1731
PavolVican92f23622017-12-12 13:35:56 +01001732 for (i = 0; i < tpdf->ext_size; ++i) {
1733 /* set flag, which represent LYEXT_OPT_VALID */
1734 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001735 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001736 break;
1737 }
1738 }
1739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001741
1742error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001744}
1745
Radek Krejcia1a6b762016-11-14 09:53:38 +09001746static int
Radek Krejcie534c132016-11-23 13:32:31 +01001747fill_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 +09001748{
Michal Vasko53b7da02018-02-13 15:28:42 +01001749 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001750 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001751 struct lyxml_elem *child, *node, *next, *next2;
1752 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001753 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001754
Michal Vasko53b7da02018-02-13 15:28:42 +01001755 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001756
Michal Vasko53b7da02018-02-13 15:28:42 +01001757 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001758 goto error;
1759 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001760 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001761
Radek Krejci07d0fb92017-01-13 14:11:05 +01001762 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001763 goto error;
1764 }
1765
Radek Krejcie534c132016-11-23 13:32:31 +01001766 LY_TREE_FOR_SAFE(yin->child, next, node) {
1767 if (strcmp(node->ns->value, LY_NSYIN)) {
1768 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001769 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001770 c_ext++;
1771 } else if (!strcmp(node->name, "argument")) {
1772 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001773 GETVAL(ctx, value, node, "name");
1774 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001775 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001776 goto error;
1777 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001778
Radek Krejcia1a6b762016-11-14 09:53:38 +09001779 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001780 LY_TREE_FOR_SAFE(node->child, next2, child) {
1781 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001782 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001783 if (ly_strequal(value, "true", 0)) {
1784 ext->flags |= LYS_YINELEM;
1785 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001786
Radek Krejci8d6b7422017-02-03 14:42:13 +01001787 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001788 goto error;
1789 }
Radek Krejcie534c132016-11-23 13:32:31 +01001790 } else if (child->ns) {
1791 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001792 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001793 goto error;
1794 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001795 }
1796
Michal Vasko53b7da02018-02-13 15:28:42 +01001797 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001798 } else {
1799 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001800 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001801 goto error;
1802 }
1803 }
1804
1805 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001806 /* some extensions may be already present from the substatements */
1807 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001808 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001809 ext->ext = reallocated;
1810
1811 /* init memory */
1812 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1813
1814 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001815 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001816 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 +01001817 ext->ext_size++;
1818 if (rc) {
1819 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001820 }
1821 }
1822 }
1823
Radek Krejci0a498f82017-01-04 16:24:15 +01001824 /* search for plugin */
1825 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 +09001826
1827 return EXIT_SUCCESS;
1828
1829error:
1830 return EXIT_FAILURE;
1831}
1832
Michal Vasko0d343d12015-08-24 14:57:36 +02001833/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001834static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001835fill_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 +02001836{
Michal Vasko53b7da02018-02-13 15:28:42 +01001837 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001838 const char *value;
1839 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001840 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001841 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001842
Michal Vasko53b7da02018-02-13 15:28:42 +01001843 GETVAL(ctx, value, yin, "name");
1844 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001845 goto error;
1846 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001847 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001848 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001849
Radek Krejci07d0fb92017-01-13 14:11:05 +01001850 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001851 goto error;
1852 }
1853
Radek Krejcie534c132016-11-23 13:32:31 +01001854 LY_TREE_FOR(yin->child, child) {
1855 if (strcmp(child->ns->value, LY_NSYIN)) {
1856 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001857 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001858 c_ext++;
1859 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001860 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001861 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001862 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001863 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001864 goto error;
1865 }
1866 }
1867
Radek Krejcie534c132016-11-23 13:32:31 +01001868 if (c_ftrs) {
1869 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001870 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001871 }
Radek Krejcie534c132016-11-23 13:32:31 +01001872 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001873 /* some extensions may be already present from the substatements */
1874 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001875 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001876 f->ext = reallocated;
1877
1878 /* init memory */
1879 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001880 }
1881
Radek Krejcie534c132016-11-23 13:32:31 +01001882 LY_TREE_FOR_SAFE(yin->child, next, child) {
1883 if (strcmp(child->ns->value, LY_NSYIN)) {
1884 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001885 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 +01001886 f->ext_size++;
1887 if (ret) {
1888 goto error;
1889 }
1890 } else { /* if-feature */
1891 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1892 f->iffeature_size++;
1893 if (ret) {
1894 goto error;
1895 }
1896 }
1897 }
1898
Radek Krejcic79c6b12016-07-26 15:11:49 +02001899 /* check for circular dependencies */
1900 if (f->iffeature_size) {
1901 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1902 goto error;
1903 }
1904 }
1905
Radek Krejci3cf9e222015-06-18 11:37:50 +02001906 return EXIT_SUCCESS;
1907
1908error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001909 return EXIT_FAILURE;
1910}
1911
Michal Vasko0d343d12015-08-24 14:57:36 +02001912/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001914fill_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 +02001915{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001916 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001917
Michal Vasko53b7da02018-02-13 15:28:42 +01001918 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001919 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001920 if (!must->expr) {
1921 goto error;
1922 }
Radek Krejci800af702015-06-02 13:46:01 +02001923
Radek Krejciaa9c5202017-02-15 16:10:14 +01001924 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001925
Michal Vasko77dc5652016-02-15 12:32:42 +01001926error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001927 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001928}
1929
Radek Krejci581ce772015-11-10 17:22:40 +01001930static int
Radek Krejci7417a082017-02-16 11:07:59 +01001931fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1932 struct unres_schema *unres)
1933{
Michal Vasko53b7da02018-02-13 15:28:42 +01001934 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001935 struct lyxml_elem *next, *child;
1936 const char *value;
1937
Michal Vasko53b7da02018-02-13 15:28:42 +01001938 GETVAL(ctx, value, yin, "date");
1939 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001940 goto error;
1941 }
1942 memcpy(rev->date, value, LY_REV_SIZE - 1);
1943
1944 LY_TREE_FOR_SAFE(yin->child, next, child) {
1945 if (!child->ns) {
1946 /* garbage */
1947 continue;
1948 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1949 /* possible extension instance */
1950 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1951 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1952 goto error;
1953 }
1954 } else if (!strcmp(child->name, "description")) {
1955 if (rev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001956 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001957 goto error;
1958 }
1959 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1960 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1961 goto error;
1962 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001963 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001964 if (!rev->dsc) {
1965 goto error;
1966 }
1967 } else if (!strcmp(child->name, "reference")) {
1968 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001969 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001970 goto error;
1971 }
1972 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1973 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1974 goto error;
1975 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001976 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001977 if (!rev->ref) {
1978 goto error;
1979 }
1980 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001981 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001982 goto error;
1983 }
1984 }
1985
1986 return EXIT_SUCCESS;
1987
1988error:
1989 return EXIT_FAILURE;
1990}
1991
1992static int
Michal Vasko88c29542015-11-27 14:57:53 +01001993fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1994 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001995{
Michal Vasko53b7da02018-02-13 15:28:42 +01001996 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02001997 int i, j, ret = EXIT_FAILURE;
1998 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02001999 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002000 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01002001
2002 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01002003 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01002004
2005 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002006 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01002007 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002008 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002009 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02002010 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01002011 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01002012 while (isspace(*vaux)) {
2013 vaux++;
2014 }
2015 }
2016 unique->expr_size++;
2017 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002018 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002019
2020 for (i = 0; i < unique->expr_size; i++) {
2021 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02002022 if (vaux) {
2023 c = *vaux;
2024 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01002025 }
2026
2027 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002028 unique->expr[i] = transform_schema2json(module, value);
2029 if (vaux) {
2030 *vaux = c;
2031 }
Radek Krejci581ce772015-11-10 17:22:40 +01002032
2033 /* check that the expression does not repeat */
2034 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002035 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002036 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
2037 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01002038 goto error;
2039 }
2040 }
2041
2042 /* try to resolve leaf */
2043 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002044 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01002045 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02002046 unique_info->list = parent;
2047 unique_info->expr = unique->expr[i];
2048 unique_info->trg_type = &unique->trg_type;
2049 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02002050 goto error;
2051 }
Radek Krejci581ce772015-11-10 17:22:40 +01002052 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002053 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002054 goto error;
2055 }
2056 }
2057
2058 /* move to next token */
2059 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002060 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002061 value++;
2062 }
2063 }
2064
Radek Krejci1a9c3612017-04-24 14:49:43 +02002065 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002066
2067error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002068 free(start);
2069 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002070}
2071
Michal Vasko0d343d12015-08-24 14:57:36 +02002072/* logs directly
2073 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002074 * type: 0 - min, 1 - max
2075 */
2076static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002077deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002078{
2079 const char *value;
2080 char *endptr;
2081 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002082 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002083 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002084
Michal Vaskof7e57d52016-03-07 11:31:09 +01002085 /* del min/max is forbidden */
2086 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002087 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002088 goto error;
2089 }
2090
Radek Krejcieb00f512015-07-01 16:44:58 +02002091 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002092 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002093 max = &((struct lys_node_leaflist *)target)->max;
2094 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002095 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002096 max = &((struct lys_node_list *)target)->max;
2097 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002099 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2100 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002101 goto error;
2102 }
2103
Michal Vasko53b7da02018-02-13 15:28:42 +01002104 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002105 while (isspace(value[0])) {
2106 value++;
2107 }
2108
Radek Krejci0d7b2472016-02-12 11:11:03 +01002109 if (type && !strcmp(value, "unbounded")) {
2110 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002111 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002112 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002113 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002114 /* convert it to uint32_t */
2115 errno = 0;
2116 endptr = NULL;
2117 val = strtoul(value, &endptr, 10);
2118 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002119 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002120 goto error;
2121 }
2122 if (type) {
2123 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002124 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002125 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002126 } else {
2127 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002128 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002129 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002130 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002131 }
2132
2133 if (d->mod == LY_DEVIATE_ADD) {
2134 /* check that there is no current value */
2135 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002136 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2137 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002138 goto error;
2139 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002140 } else if (d->mod == LY_DEVIATE_RPL) {
2141 /* unfortunately, there is no way to check reliably that there
2142 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002143 }
2144
Michal Vaskof7e57d52016-03-07 11:31:09 +01002145 /* add (already checked) and replace */
2146 /* set new value specified in deviation */
2147 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002148
Pavol Vican09adcc32016-08-25 10:51:36 +02002149 /* check min-elements is smaller than max-elements */
2150 if (*max && *min > *max) {
2151 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002152 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2153 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002154 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002155 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2156 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002157 }
2158 goto error;
2159 }
2160
Radek Krejcieb00f512015-07-01 16:44:58 +02002161 return EXIT_SUCCESS;
2162
2163error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002164 return EXIT_FAILURE;
2165}
2166
Michal Vasko0d343d12015-08-24 14:57:36 +02002167/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002168static int
Michal Vasko88c29542015-11-27 14:57:53 +01002169fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2170 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002171{
2172 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002173 struct lyxml_elem *next, *next2, *child, *develem;
2174 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002175 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002176 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002177 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002178 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002179 struct lys_deviate *d = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002180 struct lys_node *node, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002181 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002182 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002183 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002184 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002185 struct lys_node_leaflist *llist = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002186 struct lys_node_inout *inout;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002187 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002188 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002189 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002190 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002191 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002192 void *reallocated;
Andrew Langefeldf9763242018-09-16 22:23:50 -05002193 size_t deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002194
Michal Vasko53b7da02018-02-13 15:28:42 +01002195 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002196 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002197 if (!dev->target_name) {
2198 goto error;
2199 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002200
2201 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002202 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2203 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002204 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002205 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002206 goto error;
2207 }
Michal Vasko50576712017-07-28 12:28:33 +02002208 dev_target = set->set.s[0];
2209 ly_set_free(set);
2210
Radek Krejcic4283442016-04-22 09:19:27 +02002211 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002212 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2213 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002214 goto error;
2215 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002216
2217 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002218 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002219 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002220 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002221 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002222 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2223 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002224 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002225 c_ext++;
2226 continue;
2227 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002228 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002229 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 goto error;
2231 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002232 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002233 goto error;
2234 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002235 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 if (!dev->dsc) {
2237 goto error;
2238 }
2239 } else if (!strcmp(child->name, "reference")) {
2240 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002241 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002242 goto error;
2243 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002244 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002245 goto error;
2246 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002247 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002248 if (!dev->ref) {
2249 goto error;
2250 }
2251 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002252 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002253 c_dev++;
2254
Michal Vasko345da0a2015-12-02 10:35:55 +01002255 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002256 * further processed later
2257 */
2258 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002259
Radek Krejcieb00f512015-07-01 16:44:58 +02002260 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002261 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002262 goto error;
2263 }
2264
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002265 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002266 }
2267
2268 if (c_dev) {
2269 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002270 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002271 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002272 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002273 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002274 }
Radek Krejcie534c132016-11-23 13:32:31 +01002275 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002276 /* some extensions may be already present from the substatements */
2277 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002278 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002279 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002280
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002281 /* init memory */
2282 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2283 }
Radek Krejcie534c132016-11-23 13:32:31 +01002284
2285 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2286 if (strcmp(develem->ns->value, LY_NSYIN)) {
2287 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002288 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 +01002289 dev->ext_size++;
2290 if (rc) {
2291 goto error;
2292 }
2293 continue;
2294 }
2295
2296 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002297 /* init */
2298 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002299 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002300 c_must = 0;
2301 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002302 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002303 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002304
2305 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002306 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002307 if (!strcmp(value, "not-supported")) {
2308 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002309 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002310 * not-supported deviation must be the only deviation of the target
2311 */
2312 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002313 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2314 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 +02002315 goto error;
2316 }
2317
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002318 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002319 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2320 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2321 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002322 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2323 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002324 goto error;
2325 }
2326 }
2327 }
Radek Krejci5b917642015-07-02 09:03:13 +02002328
Michal Vaskoff006c12016-02-17 11:15:19 +01002329 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002330 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002331 lys_node_unlink(dev_target);
Michal Vasko5df038e2018-08-02 09:41:26 +02002332 if (parent) {
2333 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
2334 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2335 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2336 * path), so we need to remember the augment as an addition */
2337 /* remember uses parent so we can reconnect to it */
2338 dev_target->parent = parent;
2339 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
2340 /* re-create implicit node */
2341 inout = calloc(1, sizeof *inout);
2342 LY_CHECK_ERR_GOTO(!inout, LOGMEM(ctx), error);
2343
2344 inout->nodetype = dev_target->nodetype;
2345 inout->name = lydict_insert(ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
2346 inout->module = dev_target->module;
2347 inout->flags = LYS_IMPLICIT;
2348
2349 /* insert it manually */
2350 assert(parent->child && !parent->child->next
2351 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
2352 parent->child->next = (struct lys_node *)inout;
2353 inout->prev = parent->child;
2354 parent->child->prev = (struct lys_node *)inout;
2355 inout->parent = parent;
2356 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01002357 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002358 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002359
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 } else if (!strcmp(value, "add")) {
2361 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2362 } else if (!strcmp(value, "replace")) {
2363 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2364 } else if (!strcmp(value, "delete")) {
2365 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2366 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002367 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002368 goto error;
2369 }
2370 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002371 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002372
Michal Vaskoff006c12016-02-17 11:15:19 +01002373 /* store a shallow copy of the original node */
2374 if (!dev->orig_node) {
2375 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002376 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002377 /* just to be safe */
2378 if (tmp_unres.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002379 LOGINT(ctx);
Michal Vaskoff006c12016-02-17 11:15:19 +01002380 goto error;
2381 }
2382 }
2383
Radek Krejcieb00f512015-07-01 16:44:58 +02002384 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002385 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002386 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002387 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002388 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002389 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002390 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2391 /* extensions */
Michal Vasko53b7da02018-02-13 15:28:42 +01002392 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, d->ext_size, "extensions", "deviate", error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002393 c_ext++;
2394 } else if (d->mod == LY_DEVIATE_NO) {
2395 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002396 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002397 goto error;
2398 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002399 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002400 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002401 goto error;
2402 }
2403
2404 /* for we deviate from RFC 6020 and allow config property even it is/is not
2405 * specified in the target explicitly since config property inherits. So we expect
2406 * that config is specified in every node. But for delete, we check that the value
2407 * is the same as here in deviation
2408 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002409 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002410 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002411 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002412 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002413 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002414 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002415 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002416 goto error;
2417 }
2418
2419 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002420 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002421 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002422 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002423 } else { /* add and replace are the same in this case */
2424 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002425 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002426
2427 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002428 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002429 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002430
Radek Krejci8d6b7422017-02-03 14:42:13 +01002431 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002432 goto error;
2433 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002434 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002435 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 +01002436 goto error;
2437 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002438 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002439 c_dflt++;
2440
2441 /* check target node type */
2442 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002443 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2444 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002445 goto error;
2446 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002447 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2448 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002449 goto error;
2450 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002451 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2452 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002453 goto error;
2454 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002455
Radek Krejcid5a5c282016-08-15 15:38:08 +02002456 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2457 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002458
Radek Krejcieb00f512015-07-01 16:44:58 +02002459 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002460 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002461 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002462 goto error;
2463 }
2464
2465 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002466 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002467 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2468 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002469 goto error;
2470 }
2471
Michal Vasko53b7da02018-02-13 15:28:42 +01002472 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002473 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002474 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002475 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002476 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002477 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002478 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002479 goto error;
2480 }
2481
2482 if (d->mod == LY_DEVIATE_ADD) {
2483 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002484 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002485 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2486 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002487 goto error;
2488 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002489
Radek Krejci841ec082016-04-05 13:05:17 +02002490 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002491 if (d->flags & LYS_MAND_TRUE) {
2492 if (dev_target->nodetype == LYS_CHOICE) {
2493 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002494 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2495 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002496 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2497 goto error;
2498 }
2499 } else if (dev_target->nodetype == LYS_LEAF) {
2500 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002501 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2502 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002503 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2504 goto error;
2505 }
2506 }
Radek Krejci841ec082016-04-05 13:05:17 +02002507 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002508
Michal Vasko21be1b32016-03-07 12:31:34 +01002509 dev_target->flags |= d->flags & LYS_MAND_MASK;
2510 } else if (d->mod == LY_DEVIATE_RPL) {
2511 /* check that there was a value before */
2512 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002513 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2514 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002515 goto error;
2516 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002517
Michal Vasko21be1b32016-03-07 12:31:34 +01002518 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002519 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002520 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002521 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002522 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002523 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002524 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002525
2526 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2527 for (parent = dev_target->parent;
2528 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2529 parent = parent->parent) {
2530 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2531 /* stop also on presence containers */
2532 break;
2533 }
2534 }
2535 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2536 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2537 if (lyp_check_mandatory_choice(parent)) {
2538 goto error;
2539 }
2540 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002541
Radek Krejci8d6b7422017-02-03 14:42:13 +01002542 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002543 goto error;
2544 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002545 } else if (!strcmp(child->name, "min-elements")) {
2546 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002547 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002548 goto error;
2549 }
2550 f_min = 1;
2551
Michal Vasko60f4b452016-02-12 11:02:55 +01002552 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002553 goto error;
2554 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002555 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002556 goto error;
2557 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002558 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002559 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002560 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002561 goto error;
2562 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002563 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002564
Michal Vasko60f4b452016-02-12 11:02:55 +01002565 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002566 goto error;
2567 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002568 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002569 goto error;
2570 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002571 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002572 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002573 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002574 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002575 continue;
2576 } else if (!strcmp(child->name, "type")) {
2577 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002578 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002579 goto error;
2580 }
2581
Michal Vaskof7e57d52016-03-07 11:31:09 +01002582 /* add, del type is forbidden */
2583 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002584 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002585 goto error;
2586 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002587 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002588 goto error;
2589 }
2590
Radek Krejcieb00f512015-07-01 16:44:58 +02002591 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002592 if (dev_target->nodetype == LYS_LEAF) {
2593 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002594 if (((struct lys_node_leaf *)dev_target)->dflt) {
2595 ly_set_add(dflt_check, dev_target, 0);
2596 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002597 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2598 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002599 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2600 ly_set_add(dflt_check, dev_target, 0);
2601 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002602 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002603 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2604 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002605 goto error;
2606 }
2607
Radek Krejcieb00f512015-07-01 16:44:58 +02002608 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002609 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002610 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002611 /* HACK for unres */
2612 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002613 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002614 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002615 goto error;
2616 }
2617 d->type = t;
2618 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002619 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 +01002620 goto error;
2621 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002622 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002623 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002624 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002625 continue;
2626 } else if (!strcmp(child->name, "units")) {
2627 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002628 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002629 goto error;
2630 }
2631
2632 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002633 if (dev_target->nodetype == LYS_LEAFLIST) {
2634 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2635 } else if (dev_target->nodetype == LYS_LEAF) {
2636 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002637 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002638 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2639 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002640 goto error;
2641 }
2642
2643 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002644 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002645 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002646
2647 /* apply to target */
2648 if (d->mod == LY_DEVIATE_ADD) {
2649 /* check that there is no current value */
2650 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002651 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2652 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002653 goto error;
2654 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002655
Michal Vasko21be1b32016-03-07 12:31:34 +01002656 *stritem = lydict_insert(ctx, value, 0);
2657 } else if (d->mod == LY_DEVIATE_RPL) {
2658 /* check that there was a value before */
2659 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002660 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2661 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002662 goto error;
2663 }
2664
2665 lydict_remove(ctx, *stritem);
2666 *stritem = lydict_insert(ctx, value, 0);
2667 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002668 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002669 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002670 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2671 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002672 goto error;
2673 }
2674 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002675 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002676 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002677
2678 /* remove its extensions */
2679 j = -1;
2680 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2681 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2682 --j;
2683 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002684 }
2685
Radek Krejci8d6b7422017-02-03 14:42:13 +01002686 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002687 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002688 }
2689 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002690 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002691 goto error;
2692 }
2693
Michal Vasko88c29542015-11-27 14:57:53 +01002694 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002695 }
2696
2697 if (c_must) {
2698 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002699 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002700 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002701 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2702 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002703 break;
Radek Krejci76512572015-08-04 09:47:08 +02002704 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002705 trg_must = &((struct lys_node_container *)dev_target)->must;
2706 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002707 break;
Radek Krejci76512572015-08-04 09:47:08 +02002708 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002709 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2710 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002711 break;
Radek Krejci76512572015-08-04 09:47:08 +02002712 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002713 trg_must = &((struct lys_node_list *)dev_target)->must;
2714 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002715 break;
Radek Krejci76512572015-08-04 09:47:08 +02002716 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002717 case LYS_ANYDATA:
2718 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2719 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002720 break;
2721 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002722 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2723 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002724 goto error;
2725 }
2726
Michal Vaskoc04173b2018-03-09 10:43:22 +01002727 dev_target->flags &= ~(LYS_XPCONF_DEP | LYS_XPSTATE_DEP);
Michal Vasko508a50d2016-09-07 14:50:33 +02002728
Radek Krejcieb00f512015-07-01 16:44:58 +02002729 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002730 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002731 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002732 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002733 } else if (d->mod == LY_DEVIATE_ADD) {
2734 /* reallocate the must array of the target */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002735 struct lys_restr *must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
2736 LY_CHECK_ERR_GOTO(!must, LOGMEM(ctx), error);
2737 *trg_must = must;
2738 d->must = calloc(c_must, sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02002739 d->must_size = c_must;
2740 } else { /* LY_DEVIATE_DEL */
2741 d->must = calloc(c_must, sizeof *d->must);
2742 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002743 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002744 }
2745 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002746 /* replace unique is forbidden */
2747 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002748 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002749 goto error;
2750 }
2751
Radek Krejcieb00f512015-07-01 16:44:58 +02002752 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002753 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002754 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2755 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002756 goto error;
2757 }
2758
Michal Vasko60f4b452016-02-12 11:02:55 +01002759 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002760 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002761 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002762 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002763 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002764 list->unique = d->unique;
2765 d->unique = &list->unique[list->unique_size];
2766 d->unique_size = c_uniq;
2767 } else { /* LY_DEVIATE_DEL */
2768 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002769 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002770 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002771 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002772 if (c_dflt) {
2773 if (d->mod == LY_DEVIATE_ADD) {
2774 /* check that there is no current value */
2775 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2776 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002777 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2778 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002779 goto error;
2780 }
2781
2782 /* check collision with mandatory/min-elements */
2783 if ((dev_target->flags & LYS_MAND_TRUE) ||
2784 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002785 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2786 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002787 "Adding the \"default\" statement is forbidden on %s statement.",
2788 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2789 goto error;
2790 }
2791 } else if (d->mod == LY_DEVIATE_RPL) {
2792 /* check that there was a value before */
2793 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2794 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002795 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2796 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002797 goto error;
2798 }
2799 }
2800
2801 if (dev_target->nodetype == LYS_LEAFLIST) {
2802 /* reallocate default list in the target */
2803 llist = (struct lys_node_leaflist *)dev_target;
2804 if (d->mod == LY_DEVIATE_ADD) {
2805 /* reallocate (enlarge) the unique array of the target */
2806 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002807 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002808 } else if (d->mod == LY_DEVIATE_RPL) {
2809 /* reallocate (replace) the unique array of the target */
2810 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002811 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002812 }
2813 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2814 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002815 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002816 }
2817 }
2818 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002819 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002820 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002821 if (c_ext) {
2822 /* some extensions may be already present from the substatements */
2823 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002824 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002825 d->ext = reallocated;
2826
2827 /* init memory */
2828 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2829 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002830
2831 /* process deviation properties with 0..n cardinality */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002832 deviate_must_index = 0;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002833 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2834 if (strcmp(child->ns->value, LY_NSYIN)) {
2835 /* extension */
2836 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2837 goto error;
2838 }
2839 d->ext_size++;
2840 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002841 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002842 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002843 goto error;
2844 }
2845
2846 /* find must to delete, we are ok with just matching conditions */
2847 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002848 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002849 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002850 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002851 /* ... and maintain the array */
2852 (*trg_must_size)--;
2853 if (i != *trg_must_size) {
2854 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2855 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2856 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2857 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2858 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2859 }
2860 if (!(*trg_must_size)) {
2861 free(*trg_must);
2862 *trg_must = NULL;
2863 } else {
2864 (*trg_must)[*trg_must_size].expr = NULL;
2865 (*trg_must)[*trg_must_size].dsc = NULL;
2866 (*trg_must)[*trg_must_size].ref = NULL;
2867 (*trg_must)[*trg_must_size].eapptag = NULL;
2868 (*trg_must)[*trg_must_size].emsg = NULL;
2869 }
2870
2871 i = -1; /* set match flag */
2872 break;
2873 }
2874 }
2875 d->must_size++;
2876 if (i != -1) {
2877 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002878 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002879 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002880 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002881 goto error;
2882 }
2883 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002884 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002885 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002886 goto error;
2887 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05002888 memcpy(d->must + deviate_must_index, &((*trg_must)[*trg_must_size]), sizeof *d->must);
2889 ++deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002890 (*trg_must_size)++;
2891 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002892
2893 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002894 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2895 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002896 goto error;
2897 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002898 } else if (!strcmp(child->name, "unique")) {
2899 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002900 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002901 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002902 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002903 goto error;
2904 }
2905
2906 /* find unique structures to delete */
2907 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002908 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002909 continue;
2910 }
2911
Radek Krejci581ce772015-11-10 17:22:40 +01002912 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002913 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002914 break;
2915 }
2916 }
2917
Radek Krejci581ce772015-11-10 17:22:40 +01002918 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002919 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002920 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002921 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002922 }
2923 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002924 /* ... and maintain the array */
2925 list->unique_size--;
2926 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002927 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2928 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002929 }
2930
2931 if (!list->unique_size) {
2932 free(list->unique);
2933 list->unique = NULL;
2934 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002935 list->unique[list->unique_size].expr_size = 0;
2936 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002937 }
2938
Radek Krejci6bd2c022017-02-01 15:04:49 +01002939 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002940 i = -1; /* set match flag */
2941 break;
2942 }
2943 }
2944
2945 d->unique_size++;
2946 if (i != -1) {
2947 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002948 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2949 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002950 goto error;
2951 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002952
2953 /* remove extensions of this unique instance from the target node */
2954 j = -1;
2955 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 +01002956 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002957 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2958 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002959 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002960 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002961 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002962 }
2963 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002964 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002965 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002966 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002967 list->unique_size++;
2968 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002969 goto error;
2970 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002971 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002972 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002973 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002974 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002975 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002976
2977 if (dev_target->nodetype == LYS_CHOICE) {
2978 choice = (struct lys_node_choice *)dev_target;
2979 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2980 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002981 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002982 goto error;
2983 }
2984 if (d->mod == LY_DEVIATE_DEL) {
2985 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002986 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2987 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002988 goto error;
2989 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002990 choice->dflt = NULL;
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 or replace */
2998 choice->dflt = node;
2999 if (!choice->dflt) {
3000 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01003001 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003002 goto error;
3003 }
3004 }
3005 } else if (dev_target->nodetype == LYS_LEAF) {
3006 leaf = (struct lys_node_leaf *)dev_target;
3007 if (d->mod == LY_DEVIATE_DEL) {
3008 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003009 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3010 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003011 goto error;
3012 }
3013 /* remove value */
3014 lydict_remove(ctx, leaf->dflt);
3015 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01003016 leaf->flags &= ~LYS_DFLTJSON;
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) {
3021 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3022 --j;
3023 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003024 } else { /* add (already checked) and replace */
3025 /* remove value */
3026 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01003027 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003028
3029 /* set new value */
3030 leaf->dflt = lydict_insert(ctx, value, u);
3031
Radek Krejcibd117f02016-11-04 16:28:08 +01003032 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02003033 ly_set_add(dflt_check, dev_target, 0);
3034 }
3035 } else { /* LYS_LEAFLIST */
3036 llist = (struct lys_node_leaflist *)dev_target;
3037 if (d->mod == LY_DEVIATE_DEL) {
3038 /* find and remove the value in target list */
3039 for (i = 0; i < llist->dflt_size; i++) {
3040 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
3041 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01003042 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003043 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003044
3045 /* remove extensions of this default instance from the target node */
3046 j = -1;
3047 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 +01003048 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003049 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3050 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003051 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003052 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003053 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003054 }
3055 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003056 break;
3057 }
3058 }
3059 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003060 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3061 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 +02003062 goto error;
3063 }
3064 } else {
3065 /* add or replace, anyway we place items into the deviate's list
3066 which propagates to the target */
3067 /* we just want to check that the value isn't already in the list */
3068 for (i = 0; i < llist->dflt_size; i++) {
3069 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003070 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3071 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003072 goto error;
3073 }
3074 }
3075 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003076 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003077
3078 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3079 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003080 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003081 }
3082 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003083 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003084 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003085
3086 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3087 /* consolidate the final list in the target after removing items from it */
3088 llist = (struct lys_node_leaflist *)dev_target;
3089 for (i = j = 0; j < llist->dflt_size; j++) {
3090 llist->dflt[i] = llist->dflt[j];
3091 if (llist->dflt[i]) {
3092 i++;
3093 }
3094 }
3095 llist->dflt_size = i + 1;
3096 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003097 }
3098
Michal Vasko43a1feb2016-03-07 12:03:02 +01003099 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003100 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003101 for (u = 0; u < dflt_check->number; ++u) {
3102 value = NULL;
3103 rc = EXIT_SUCCESS;
3104 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3105 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3106 value = leaf->dflt;
3107 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3108 } else { /* LYS_LEAFLIST */
3109 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3110 for (j = 0; j < llist->dflt_size; j++) {
3111 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3112 (struct lys_node *)(&llist->dflt[j]));
3113 if (rc == -1) {
3114 value = llist->dflt[j];
3115 break;
3116 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003117 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003118
Michal Vasko15a43372017-09-25 14:12:42 +02003119 }
3120 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003121 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3122 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003123 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3124 dev->target_name);
3125 goto error;
3126 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003127 }
3128 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003129
Radek Krejci27fe55e2016-09-13 17:13:35 +02003130 /* mark all the affected modules as deviated and implemented */
3131 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3132 mod = lys_node_module(parent);
3133 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003134 mod->deviated = 1; /* main module */
3135 parent->module->deviated = 1; /* possible submodule */
Michal Vasko0f437062018-06-08 15:52:39 +02003136 if (!mod->implemented) {
3137 mod->implemented = 1;
3138 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
3139 goto error;
3140 }
Radek Krejci2bb5be72017-02-27 13:07:25 +01003141 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003142 }
3143 }
3144
Radek Krejcid5a5c282016-08-15 15:38:08 +02003145 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003146 return EXIT_SUCCESS;
3147
3148error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003149 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003150 return EXIT_FAILURE;
3151}
3152
Michal Vasko0d343d12015-08-24 14:57:36 +02003153/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003154static int
Radek Krejcib8048692015-08-05 13:36:34 +02003155fill_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 +01003156 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003157{
Michal Vasko53b7da02018-02-13 15:28:42 +01003158 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003160 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003161 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003162 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003163 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003164
Michal Vasko591e0b22015-08-13 13:53:43 +02003165 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003166 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003167 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003168 if (!aug->target_name) {
3169 goto error;
3170 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003172
Radek Krejci07d0fb92017-01-13 14:11:05 +01003173 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003174 goto error;
3175 }
3176
Radek Krejcie534c132016-11-23 13:32:31 +01003177 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3178 if (strcmp(sub->ns->value, LY_NSYIN)) {
3179 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003180 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003181 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003182 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003183 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003184 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003185 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003186 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003187 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003188 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003189 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003190 goto error;
3191 }
3192
Radek Krejci5323b492017-01-16 15:40:11 +01003193 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003194 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003195 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003196 goto error;
3197 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003198 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003199 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003200
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003201 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003202 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003203 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003204 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003205 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003206 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003207 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003208 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003209 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003210 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003211 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003212 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003213 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003214 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003215 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003216 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003217 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003218 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003219 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003220 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003221 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003222 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003223 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003224 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003225 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003226 goto error;
3227 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003228
Radek Krejci1d82ef62015-08-07 14:44:40 +02003229 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003230 goto error;
3231 }
3232
Radek Krejci1d82ef62015-08-07 14:44:40 +02003233 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003234 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003235 }
3236
Radek Krejcie534c132016-11-23 13:32:31 +01003237 if (c_ftrs) {
3238 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003239 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003240 }
Radek Krejcie534c132016-11-23 13:32:31 +01003241 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003242 /* some extensions may be already present from the substatements */
3243 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003244 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003245 aug->ext = reallocated;
3246
3247 /* init memory */
3248 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003249 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003250
Radek Krejcie534c132016-11-23 13:32:31 +01003251 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3252 if (strcmp(sub->ns->value, LY_NSYIN)) {
3253 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003254 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 +01003255 aug->ext_size++;
3256 if (ret) {
3257 goto error;
3258 }
3259 } else if (!strcmp(sub->name, "if-feature")) {
3260 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003261 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003262 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003263 goto error;
3264 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003265 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003266 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003267 }
3268
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003269 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003270 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003271 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003272 * when the uses does and cannot be resolved now for sure
3273 * (the grouping was not yet copied into uses).
3274 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003275 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003276 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003277 goto error;
3278 }
Michal Vasko49291b32015-08-06 09:49:41 +02003279 }
Radek Krejci106efc02015-06-10 14:36:27 +02003280
Michal Vasko508a50d2016-09-07 14:50:33 +02003281 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003282 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003283 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003284 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003285 goto error;
3286 }
3287 } else {
3288 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3289 goto error;
3290 }
3291 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003292 }
3293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003295
3296error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003298}
3299
Michal Vasko0d343d12015-08-24 14:57:36 +02003300/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003302fill_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 +02003303{
Michal Vasko53b7da02018-02-13 15:28:42 +01003304 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003305 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 struct lyxml_elem *sub, *next;
3307 const char *value;
3308 char *endptr;
3309 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003310 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 int r;
3312 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003313 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003314
Radek Krejci363bd4a2016-07-29 14:30:20 +02003315 assert(uses);
3316 module = uses->module; /* shorthand */
3317
Michal Vasko53b7da02018-02-13 15:28:42 +01003318 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003319 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003320 if (!rfn->target_name) {
3321 goto error;
3322 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003325 if (!sub->ns) {
3326 /* garbage */
3327 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003328 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003329 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003330 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003331 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003332
Radek Krejci411b1bf2017-01-23 16:40:05 +01003333 } else if (!strcmp(sub->name, "description")) {
3334 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003335 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003336 goto error;
3337 }
3338
Radek Krejci8d6b7422017-02-03 14:42:13 +01003339 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003340 goto error;
3341 }
3342
Michal Vasko53b7da02018-02-13 15:28:42 +01003343 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003344 if (!rfn->dsc) {
3345 goto error;
3346 }
3347 } else if (!strcmp(sub->name, "reference")) {
3348 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003349 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003350 goto error;
3351 }
3352
Radek Krejci8d6b7422017-02-03 14:42:13 +01003353 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003354 goto error;
3355 }
3356
Michal Vasko53b7da02018-02-13 15:28:42 +01003357 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003358 if (!rfn->ref) {
3359 goto error;
3360 }
3361 } else if (!strcmp(sub->name, "config")) {
3362 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003363 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003364 goto error;
3365 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003366 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003367 if (!strcmp(value, "false")) {
3368 rfn->flags |= LYS_CONFIG_R;
3369 } else if (!strcmp(value, "true")) {
3370 rfn->flags |= LYS_CONFIG_W;
3371 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003372 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003373 goto error;
3374 }
3375 rfn->flags |= LYS_CONFIG_SET;
3376
Radek Krejci8d6b7422017-02-03 14:42:13 +01003377 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003378 goto error;
3379 }
Radek Krejcie534c132016-11-23 13:32:31 +01003380 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003381 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 /* check possibility of statements combination */
3384 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003385 if (c_dflt) {
3386 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003387 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003388 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003389 goto error;
3390 }
Radek Krejci200bf712016-08-16 17:11:04 +02003391 rfn->target_type &= LYS_LEAFLIST;
3392 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003393 if (module->version < 2) {
3394 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3395 } else {
3396 /* YANG 1.1 */
3397 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3398 }
Radek Krejci200bf712016-08-16 17:11:04 +02003399 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003401 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3402 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 goto error;
3404 }
3405 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003406 if (module->version < 2) {
3407 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3408 } else {
3409 /* YANG 1.1 */
3410 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3411 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003413
Michal Vasko53b7da02018-02-13 15:28:42 +01003414 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003415 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 +01003416 goto error;
3417 }
Radek Krejci200bf712016-08-16 17:11:04 +02003418 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003419 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 } else if (!strcmp(sub->name, "mandatory")) {
3421 /* leaf, choice or anyxml */
3422 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003423 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003424 goto error;
3425 }
3426 /* just checking the flags in leaf is not sufficient, we would allow
3427 * multiple mandatory statements with the "false" value
3428 */
3429 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 /* check possibility of statements combination */
3432 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003433 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003435 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3436 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 goto error;
3438 }
3439 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003440 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003442
Michal Vasko53b7da02018-02-13 15:28:42 +01003443 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003445 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003447 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003449 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 goto error;
3451 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003452 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003453 goto error;
3454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 } else if (!strcmp(sub->name, "min-elements")) {
3456 /* list or leaf-list */
3457 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003458 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 goto error;
3460 }
3461 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 /* check possibility of statements combination */
3464 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003465 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003467 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3468 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 goto error;
3470 }
3471 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003472 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003474
Michal Vasko53b7da02018-02-13 15:28:42 +01003475 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 while (isspace(value[0])) {
3477 value++;
3478 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 /* convert it to uint32_t */
3481 errno = 0;
3482 endptr = NULL;
3483 val = strtoul(value, &endptr, 10);
3484 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003485 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 goto error;
3487 }
3488 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003489 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003490
Radek Krejci8d6b7422017-02-03 14:42:13 +01003491 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003492 goto error;
3493 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 } else if (!strcmp(sub->name, "max-elements")) {
3495 /* list or leaf-list */
3496 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003497 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 goto error;
3499 }
3500 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 /* check possibility of statements combination */
3503 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003504 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003506 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3507 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 goto error;
3509 }
3510 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003511 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003513
Michal Vasko53b7da02018-02-13 15:28:42 +01003514 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003515 while (isspace(value[0])) {
3516 value++;
3517 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003518
Radek Krejci0d7b2472016-02-12 11:11:03 +01003519 if (!strcmp(value, "unbounded")) {
3520 rfn->mod.list.max = 0;
3521 } else {
3522 /* convert it to uint32_t */
3523 errno = 0;
3524 endptr = NULL;
3525 val = strtoul(value, &endptr, 10);
3526 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003527 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003528 goto error;
3529 }
3530 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003532 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003533
Radek Krejci8d6b7422017-02-03 14:42:13 +01003534 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003535 goto error;
3536 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 } else if (!strcmp(sub->name, "presence")) {
3538 /* container */
3539 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003540 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 goto error;
3542 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 /* check possibility of statements combination */
3545 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003546 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003548 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3549 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 goto error;
3551 }
3552 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003553 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003555
Michal Vasko53b7da02018-02-13 15:28:42 +01003556 GETVAL(ctx, value, sub, "value");
3557 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003558
Radek Krejci8d6b7422017-02-03 14:42:13 +01003559 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003560 goto error;
3561 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003563 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 /* check possibility of statements combination */
3565 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003566 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003568 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3569 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 goto error;
3571 }
3572 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003573 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003575
Michal Vasko53b7da02018-02-13 15:28:42 +01003576 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003578 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003579
Radek Krejci363bd4a2016-07-29 14:30:20 +02003580 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3581 /* leaf, leaf-list, list, container or anyxml */
3582 /* check possibility of statements combination */
3583 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003584 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003585 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003586 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3587 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003588 goto error;
3589 }
3590 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003591 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003592 }
3593
Michal Vasko53b7da02018-02-13 15:28:42 +01003594 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003595 c_ftrs++;
3596 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003598 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 goto error;
3600 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003601
Michal Vasko53b7da02018-02-13 15:28:42 +01003602 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 /* process nodes with cardinality of 0..n */
3606 if (c_must) {
3607 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003608 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003610 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003611 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003612 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 }
Radek Krejci200bf712016-08-16 17:11:04 +02003614 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003615 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003616 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003617 }
Radek Krejcie534c132016-11-23 13:32:31 +01003618 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003619 /* some extensions may be already present from the substatements */
3620 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003621 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003622 rfn->ext = reallocated;
3623
3624 /* init memory */
3625 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003626 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003627
Radek Krejcie534c132016-11-23 13:32:31 +01003628 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3629 if (strcmp(sub->ns->value, LY_NSYIN)) {
3630 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003631 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 +01003632 rfn->ext_size++;
3633 if (r) {
3634 goto error;
3635 }
3636 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003637 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003638 rfn->iffeature_size++;
3639 if (r) {
3640 goto error;
3641 }
Radek Krejci200bf712016-08-16 17:11:04 +02003642 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003643 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003644 rfn->must_size++;
3645 if (r) {
3646 goto error;
3647 }
Radek Krejci200bf712016-08-16 17:11:04 +02003648 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003649 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003650
3651 /* check for duplicity */
3652 for (r = 0; r < rfn->dflt_size; r++) {
3653 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003654 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3655 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003656 goto error;
3657 }
3658 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003659 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003660 }
3661 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003664
3665error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003667}
3668
Michal Vasko0d343d12015-08-24 14:57:36 +02003669/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003670static int
Radek Krejcie534c132016-11-23 13:32:31 +01003671fill_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 +02003672{
Michal Vasko53b7da02018-02-13 15:28:42 +01003673 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003674 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003676 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003677 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003678
Radek Krejcie534c132016-11-23 13:32:31 +01003679 /* init */
3680 memset(&exts, 0, sizeof exts);
3681
3682 LY_TREE_FOR_SAFE(yin->child, next, child) {
3683 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003684 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003685 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003686 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3687 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003688 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003689 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003690 lyxml_unlink_elem(ctx, child, 2);
3691 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003692 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003693 GETVAL(ctx, value, child, "value");
3694 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 goto error;
3696 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003697 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003698
Radek Krejci8d6b7422017-02-03 14:42:13 +01003699 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003700 goto error;
3701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 } else if (!strcmp(child->name, "revision-date")) {
3703 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003704 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003705 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003707 GETVAL(ctx, value, child, "date");
3708 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 goto error;
3710 }
3711 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003712
Radek Krejci8d6b7422017-02-03 14:42:13 +01003713 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003714 goto error;
3715 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003716 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003717 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003718 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003719 goto error;
3720 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003721 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003722 goto error;
3723 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003724 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003725 if (!imp->dsc) {
3726 goto error;
3727 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003728 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003729 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003730 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003731 goto error;
3732 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003733 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003734 goto error;
3735 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003736 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003737 if (!imp->ref) {
3738 goto error;
3739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003741 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 goto error;
3743 }
3744 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 /* check mandatory information */
3747 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003748 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 goto error;
3750 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003751
Radek Krejcie534c132016-11-23 13:32:31 +01003752 /* process extensions */
3753 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003754 /* some extensions may be already present from the substatements */
3755 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003756 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003757 imp->ext = reallocated;
3758
3759 /* init memory */
3760 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3761
Radek Krejcie534c132016-11-23 13:32:31 +01003762 LY_TREE_FOR_SAFE(exts.child, next, child) {
3763 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003764 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 +01003765 imp->ext_size++;
3766 if (r) {
3767 goto error;
3768 }
3769 }
3770 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003771
Michal Vasko53b7da02018-02-13 15:28:42 +01003772 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003773 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003774
3775error:
Radek Krejcie534c132016-11-23 13:32:31 +01003776 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003777 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003778 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003779 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003780}
3781
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003782/* logs directly
3783 * returns:
3784 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003785 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003786 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003788fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3789 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003790{
Michal Vasko53b7da02018-02-13 15:28:42 +01003791 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003792 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003794 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003795 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003796
Radek Krejcie534c132016-11-23 13:32:31 +01003797 /* init */
3798 memset(&exts, 0, sizeof exts);
3799
3800 LY_TREE_FOR_SAFE(yin->child, next, child) {
3801 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003802 /* garbage */
3803 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003804 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3805 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003806 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003807 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003808 lyxml_unlink_elem(ctx, child, 2);
3809 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003810 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003811 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003812 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 goto error;
3814 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003815 GETVAL(ctx, value, child, "date");
3816 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 goto error;
3818 }
3819 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003820
Radek Krejci8d6b7422017-02-03 14:42:13 +01003821 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003822 goto error;
3823 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003824 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003825 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003826 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003827 goto error;
3828 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003829 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003830 goto error;
3831 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003832 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003833 if (!inc->dsc) {
3834 goto error;
3835 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003836 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003837 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003838 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003839 goto error;
3840 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003841 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003842 goto error;
3843 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003844 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003845 if (!inc->ref) {
3846 goto error;
3847 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003849 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 goto error;
3851 }
3852 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003853
Radek Krejcie534c132016-11-23 13:32:31 +01003854 /* process extensions */
3855 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003856 /* some extensions may be already present from the substatements */
3857 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003858 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003859 inc->ext = reallocated;
3860
3861 /* init memory */
3862 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3863
Radek Krejcie534c132016-11-23 13:32:31 +01003864 LY_TREE_FOR_SAFE(exts.child, next, child) {
3865 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003866 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 +01003867 inc->ext_size++;
3868 if (r) {
3869 goto error;
3870 }
3871 }
3872 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003873
Michal Vasko53b7da02018-02-13 15:28:42 +01003874 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003875 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003876
3877error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003878 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003879}
3880
Michal Vasko0d343d12015-08-24 14:57:36 +02003881/* logs directly
3882 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003883 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003884 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003885 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003886 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003888read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3889 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003890{
Radek Krejcie4dce292017-10-30 11:16:47 +01003891 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 const char *value;
3893 struct lyxml_elem *sub, *next;
3894 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003895 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003898 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003902 GETVAL(ctx, value, xmlnode, "name");
3903 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 goto error;
3905 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003906 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003909 /* process local parameters */
3910 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003911 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003912 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003913 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003914 continue;
3915 }
3916 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003917 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003918 continue;
3919 }
3920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003922 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003923 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 goto error;
3925 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003926
Radek Krejci8d6b7422017-02-03 14:42:13 +01003927 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003928 goto error;
3929 }
3930
Radek Krejci1d82ef62015-08-07 14:44:40 +02003931 node->dsc = read_yin_subnode(ctx, sub, "text");
3932 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003933 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 }
3935 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003936 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003937 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 goto error;
3939 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003940
Radek Krejci8d6b7422017-02-03 14:42:13 +01003941 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003942 goto error;
3943 }
3944
Radek Krejci1d82ef62015-08-07 14:44:40 +02003945 node->ref = read_yin_subnode(ctx, sub, "text");
3946 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003947 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 }
3949 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003950 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003951 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 goto error;
3953 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003954 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003958 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003962 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003963 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003965
Radek Krejci8d6b7422017-02-03 14:42:13 +01003966 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003967 goto error;
3968 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003969 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3970 if (opt & OPT_CFG_PARSE) {
3971 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003972 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003973 goto error;
3974 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003975 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003976 if (!strcmp(value, "false")) {
3977 node->flags |= LYS_CONFIG_R;
3978 } else if (!strcmp(value, "true")) {
3979 node->flags |= LYS_CONFIG_W;
3980 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003981 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003982 goto error;
3983 }
3984 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003985
Radek Krejci8d6b7422017-02-03 14:42:13 +01003986 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003987 goto error;
3988 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003990 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003991 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003992 continue;
3993 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003994 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003995 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003996
Michal Vaskoe022a562016-09-27 14:24:15 +02003997 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003999 if (parent) {
4000 node->flags |= parent->flags & LYS_CONFIG_MASK;
4001 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004002 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004003 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 }
4005 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004006
Radek Krejci2cc25322017-09-06 16:32:02 +02004007 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
4008 /* status is not inherited by specification, but it not make sense to have
4009 * current in deprecated or deprecated in obsolete, so we print warning
4010 * and fix the schema by inheriting */
4011 if (!(node->flags & (LYS_STATUS_MASK))) {
4012 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01004013 if (stmt_type == LYEXT_PAR_NODE) {
4014 p = node->parent;
4015 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01004016 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004017 node->parent = p;
4018 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01004019 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004020 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004021 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
4022 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02004023 free(str);
4024 node->flags |= parent->flags & LYS_STATUS_MASK;
4025 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
4026 /* invalid combination of statuses */
4027 switch (node->flags & LYS_STATUS_MASK) {
4028 case 0:
4029 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01004030 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004031 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
4032 break;
4033 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01004034 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004035 "obsolete", parent->name);
4036 break;
4037 }
4038 goto error;
4039 }
4040 }
4041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004042 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004043
4044error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004046}
4047
Michal Vasko0d343d12015-08-24 14:57:36 +02004048/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004049static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004050read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004051{
Michal Vasko53b7da02018-02-13 15:28:42 +01004052 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004053 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004054 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004055 const char *value;
4056
4057 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004058 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004059
Michal Vasko53b7da02018-02-13 15:28:42 +01004060 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004061 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004062 if (!retval->cond) {
4063 goto error;
4064 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004065
Radek Krejci5323b492017-01-16 15:40:11 +01004066 LY_TREE_FOR_SAFE(yin->child, next, child) {
4067 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004068 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004069 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004070 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4071 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004072 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004073 goto error;
4074 }
4075 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004076 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004077 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004078 goto error;
4079 }
Radek Krejci5323b492017-01-16 15:40:11 +01004080
Radek Krejci8d6b7422017-02-03 14:42:13 +01004081 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004082 goto error;
4083 }
4084
Michal Vasko53b7da02018-02-13 15:28:42 +01004085 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004086 if (!retval->dsc) {
4087 goto error;
4088 }
4089 } else if (!strcmp(child->name, "reference")) {
4090 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004091 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004092 goto error;
4093 }
Radek Krejci5323b492017-01-16 15:40:11 +01004094
Radek Krejci8d6b7422017-02-03 14:42:13 +01004095 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004096 goto error;
4097 }
4098
Michal Vasko53b7da02018-02-13 15:28:42 +01004099 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004100 if (!retval->ref) {
4101 goto error;
4102 }
4103 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004104 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004105 goto error;
4106 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004107 }
4108
4109 return retval;
4110
4111error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004112 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004113 return NULL;
4114}
4115
Michal Vasko0d343d12015-08-24 14:57:36 +02004116/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004117static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004118read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004119 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004120{
Michal Vasko53b7da02018-02-13 15:28:42 +01004121 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004122 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004123 struct lys_node_case *cs;
4124 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004125 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004126 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004127
Radek Krejcie867c852015-08-27 09:52:34 +02004128 /* init */
4129 memset(&root, 0, sizeof root);
4130
Radek Krejci1d82ef62015-08-07 14:44:40 +02004131 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004132 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004133 cs->nodetype = LYS_CASE;
4134 cs->prev = (struct lys_node *)cs;
4135 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004136
Radek Krejci07d0fb92017-01-13 14:11:05 +01004137 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004138 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004139 goto error;
4140 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004141
Michal Vasko3e3228d2017-02-24 14:55:32 +01004142 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004143
Michal Vasko3a0043f2015-08-12 12:11:30 +02004144 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004145 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004146 goto error;
4147 }
4148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 /* process choice's specific children */
4150 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004151 if (strcmp(sub->ns->value, LY_NSYIN)) {
4152 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004153 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004154 c_ext++;
4155 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004156 !strcmp(sub->name, "leaf-list") ||
4157 !strcmp(sub->name, "leaf") ||
4158 !strcmp(sub->name, "list") ||
4159 !strcmp(sub->name, "uses") ||
4160 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004161 !strcmp(sub->name, "anyxml") ||
4162 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004163
Michal Vasko53b7da02018-02-13 15:28:42 +01004164 lyxml_unlink_elem(ctx, sub, 2);
4165 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004166 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004167 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004168 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004169 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004170 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004171 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004172 goto error;
4173 }
4174
Radek Krejci5323b492017-01-16 15:40:11 +01004175 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004176 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004177 goto error;
4178 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004179
Michal Vasko53b7da02018-02-13 15:28:42 +01004180 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004181 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004182 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004184 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004186
Radek Krejci3cf9e222015-06-18 11:37:50 +02004187 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004188 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004189 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004190 }
Radek Krejcie534c132016-11-23 13:32:31 +01004191 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004192 /* some extensions may be already present from the substatements */
4193 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004194 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004195 retval->ext = reallocated;
4196
4197 /* init memory */
4198 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004199 }
Radek Krejci21c81652017-01-23 10:42:55 +01004200
Radek Krejcie534c132016-11-23 13:32:31 +01004201 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4202 if (strcmp(sub->ns->value, LY_NSYIN)) {
4203 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004204 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 +01004205 retval->ext_size++;
4206 if (ret) {
4207 goto error;
4208 }
4209 } else {
4210 /* if-feature */
4211 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4212 cs->iffeature_size++;
4213 if (ret) {
4214 goto error;
4215 }
4216 }
4217 }
Radek Krejcib388c152015-06-04 17:03:03 +02004218
Michal Vasko29fc0182015-08-24 15:02:39 +02004219 /* last part - process data nodes */
4220 LY_TREE_FOR_SAFE(root.child, next, sub) {
4221 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004222 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004223 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004224 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004225 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004226 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004227 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004228 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004229 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004230 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004231 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004232 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004233 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004234 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004235 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004236 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004237 }
4238 if (!node) {
4239 goto error;
4240 }
4241
Michal Vasko53b7da02018-02-13 15:28:42 +01004242 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004243 }
4244
Michal Vasko508a50d2016-09-07 14:50:33 +02004245 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004246 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004247 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004248 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004249 goto error;
4250 }
4251 } else {
4252 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4253 goto error;
4254 }
4255 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004256 }
4257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004258 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004259
4260error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004261 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004262 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004263 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004264 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004266 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004267}
4268
Michal Vasko0d343d12015-08-24 14:57:36 +02004269/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004270static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004271read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004272 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004273{
Radek Krejci629cdef2016-06-06 15:06:36 +02004274 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004275 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004276 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004277 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004278 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004279 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004280 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004283 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004284
Radek Krejci76512572015-08-04 09:47:08 +02004285 choice->nodetype = LYS_CHOICE;
4286 choice->prev = (struct lys_node *)choice;
4287 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004288
Radek Krejci07d0fb92017-01-13 14:11:05 +01004289 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004290 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4291 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4292 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004293 goto error;
4294 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004295
Michal Vasko3e3228d2017-02-24 14:55:32 +01004296 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004297
Michal Vasko3a0043f2015-08-12 12:11:30 +02004298 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004299 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004300 goto error;
4301 }
4302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004303 /* process choice's specific children */
4304 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004305 if (strcmp(sub->ns->value, LY_NSYIN)) {
4306 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004307 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004308 c_ext++;
4309 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004310 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004311 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004312 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 goto error;
4314 }
4315 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004316 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 goto error;
4318 }
4319 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004320 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 goto error;
4322 }
4323 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004324 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 goto error;
4326 }
4327 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004328 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004329 goto error;
4330 }
4331 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004332 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004333 goto error;
4334 }
4335 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004336 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 goto error;
4338 }
4339 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004340 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004341 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 goto error;
4343 }
Radek Krejci21c81652017-01-23 10:42:55 +01004344
Radek Krejci8d6b7422017-02-03 14:42:13 +01004345 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004346 goto error;
4347 }
4348
Radek Krejci629cdef2016-06-06 15:06:36 +02004349 dflt = sub;
4350 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004351 continue;
4352 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 } else if (!strcmp(sub->name, "mandatory")) {
4355 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004356 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 goto error;
4358 }
4359 /* just checking the flags in leaf is not sufficient, we would allow
4360 * multiple mandatory statements with the "false" value
4361 */
4362 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004363
Michal Vasko53b7da02018-02-13 15:28:42 +01004364 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004365 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004366 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004367 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004368 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004369 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004370 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 goto error;
4372 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004373
Radek Krejci8d6b7422017-02-03 14:42:13 +01004374 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004375 goto error;
4376 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004377 } else if (!strcmp(sub->name, "when")) {
4378 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004379 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004380 goto error;
4381 }
4382
Radek Krejci5323b492017-01-16 15:40:11 +01004383 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004384 if (!choice->when) {
4385 goto error;
4386 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004387 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004388 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004389 c_ftrs++;
4390
Michal Vasko345da0a2015-12-02 10:35:55 +01004391 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004392 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004393 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004394 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004395 goto error;
4396 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004397 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004398 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004401
Radek Krejci1d82ef62015-08-07 14:44:40 +02004402 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004403 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004405
Radek Krejci3cf9e222015-06-18 11:37:50 +02004406 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004407 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004408 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004409 }
Radek Krejcie534c132016-11-23 13:32:31 +01004410 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004411 /* some extensions may be already present from the substatements */
4412 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004413 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004414 retval->ext = reallocated;
4415
4416 /* init memory */
4417 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004418 }
4419
Radek Krejcie534c132016-11-23 13:32:31 +01004420 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4421 if (strcmp(sub->ns->value, LY_NSYIN)) {
4422 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004423 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 +01004424 retval->ext_size++;
4425 if (ret) {
4426 goto error;
4427 }
4428 } else {
4429 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4430 choice->iffeature_size++;
4431 if (ret) {
4432 goto error;
4433 }
4434 }
4435 }
4436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004437 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004438 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004439 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4440 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 goto error;
4442 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004445 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004446 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004447 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004448 goto error;
4449 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004450 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004451 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004452
Michal Vasko508a50d2016-09-07 14:50:33 +02004453 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004454 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004455 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004456 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004457 goto error;
4458 }
4459 } else {
4460 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4461 goto error;
4462 }
4463 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004464 }
4465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004467
4468error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004469 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004470 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004472}
4473
Michal Vasko0d343d12015-08-24 14:57:36 +02004474/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004475static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004476read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004477 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004478{
Michal Vasko53b7da02018-02-13 15:28:42 +01004479 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004480 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004481 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004482 struct lyxml_elem *sub, *next;
4483 const char *value;
4484 int r;
4485 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004486 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004487 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004490 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004491
Radek Krejcibf2abff2016-08-23 15:51:52 +02004492 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004493 anyxml->prev = (struct lys_node *)anyxml;
4494 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004495
Radek Krejci07d0fb92017-01-13 14:11:05 +01004496 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004497 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004498 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 goto error;
4500 }
Radek Krejci863c2852015-06-03 15:47:11 +02004501
Michal Vasko3e3228d2017-02-24 14:55:32 +01004502 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004503
Radek Krejcic189a952016-07-11 15:27:07 +02004504 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004505 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004506 goto error;
4507 }
4508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004510 if (strcmp(sub->ns->value, LY_NSYIN)) {
4511 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004512 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004513 c_ext++;
4514 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004516 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 goto error;
4518 }
4519 /* just checking the flags in leaf is not sufficient, we would allow
4520 * multiple mandatory statements with the "false" value
4521 */
4522 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004523
Michal Vasko53b7da02018-02-13 15:28:42 +01004524 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004526 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004527 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004528 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004529 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004530 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 goto error;
4532 }
4533 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004534
Radek Krejci8d6b7422017-02-03 14:42:13 +01004535 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004536 goto error;
4537 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004538 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004539 } else if (!strcmp(sub->name, "when")) {
4540 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004541 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004542 goto error;
4543 }
4544
Radek Krejci5323b492017-01-16 15:40:11 +01004545 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004546 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004547 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004548 goto error;
4549 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004550 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004551 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004552 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004553 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004554 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004555 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004556 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004559 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 }
4562 }
Radek Krejci863c2852015-06-03 15:47:11 +02004563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 /* middle part - process nodes with cardinality of 0..n */
4565 if (c_must) {
4566 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004567 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004569 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004570 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004571 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004572 }
Radek Krejcie534c132016-11-23 13:32:31 +01004573 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004574 /* some extensions may be already present from the substatements */
4575 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004576 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004577 retval->ext = reallocated;
4578
4579 /* init memory */
4580 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004581 }
Radek Krejci863c2852015-06-03 15:47:11 +02004582
Radek Krejcie534c132016-11-23 13:32:31 +01004583 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4584 if (strcmp(sub->ns->value, LY_NSYIN)) {
4585 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004586 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 +01004587 retval->ext_size++;
4588 if (r) {
4589 goto error;
4590 }
4591 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004592 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004593 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 if (r) {
4595 goto error;
4596 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004597 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004598 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004599 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004600 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004601 goto error;
4602 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004603 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004604 }
Radek Krejci863c2852015-06-03 15:47:11 +02004605
Michal Vasko508a50d2016-09-07 14:50:33 +02004606 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004607 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004608 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004609 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004610 goto error;
4611 }
4612 } else {
4613 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4614 goto error;
4615 }
4616 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004617 }
4618
PavolVican92f23622017-12-12 13:35:56 +01004619 for (r = 0; r < retval->ext_size; ++r) {
4620 /* set flag, which represent LYEXT_OPT_VALID */
4621 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004622 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004623 break;
4624 }
4625 }
4626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004627 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004628
4629error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004630 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004632}
4633
Michal Vasko0d343d12015-08-24 14:57:36 +02004634/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004635static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004636read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004637 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004638{
Michal Vasko53b7da02018-02-13 15:28:42 +01004639 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004640 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004641 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 struct lyxml_elem *sub, *next;
4643 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004644 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004645 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004646 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004649 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004650
Radek Krejci76512572015-08-04 09:47:08 +02004651 leaf->nodetype = LYS_LEAF;
4652 leaf->prev = (struct lys_node *)leaf;
4653 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004654
Radek Krejci07d0fb92017-01-13 14:11:05 +01004655 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004656 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4657 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4658 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 goto error;
4660 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004661
Michal Vasko3e3228d2017-02-24 14:55:32 +01004662 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004663
Radek Krejcic189a952016-07-11 15:27:07 +02004664 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004665 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004666 goto error;
4667 }
4668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004670 if (strcmp(sub->ns->value, LY_NSYIN)) {
4671 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004672 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004673 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004674 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004675 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004676 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004677 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 goto error;
4679 }
Michal Vasko88c29542015-11-27 14:57:53 +01004680 /* HACK for unres */
4681 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004682 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004683 /* postpone type resolution when if-feature parsing is done since we need
4684 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004685 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 } else if (!strcmp(sub->name, "default")) {
4687 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004688 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 goto error;
4690 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004691 GETVAL(ctx, value, sub, "value");
4692 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004693
Radek Krejci8d6b7422017-02-03 14:42:13 +01004694 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004695 goto error;
4696 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 } else if (!strcmp(sub->name, "units")) {
4698 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004699 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 goto error;
4701 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004702 GETVAL(ctx, value, sub, "name");
4703 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004704
Radek Krejci8d6b7422017-02-03 14:42:13 +01004705 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004706 goto error;
4707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 } else if (!strcmp(sub->name, "mandatory")) {
4709 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004710 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004711 goto error;
4712 }
4713 /* just checking the flags in leaf is not sufficient, we would allow
4714 * multiple mandatory statements with the "false" value
4715 */
4716 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004717
Michal Vasko53b7da02018-02-13 15:28:42 +01004718 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004720 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004721 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004722 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004723 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004724 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004725 goto error;
4726 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004727
Radek Krejci8d6b7422017-02-03 14:42:13 +01004728 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004729 goto error;
4730 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004731 } else if (!strcmp(sub->name, "when")) {
4732 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004733 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004734 goto error;
4735 }
4736
Radek Krejci5323b492017-01-16 15:40:11 +01004737 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004738 if (!leaf->when) {
4739 goto error;
4740 }
4741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004743 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004744 c_must++;
4745 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004746 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004747 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004748 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004752 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004755
Michal Vasko88c29542015-11-27 14:57:53 +01004756 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004759 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004760 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004761 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004762 goto error;
4763 }
Michal Vasko478c4652016-07-21 12:55:01 +02004764 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004765 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4766 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004767 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4768 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004769 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 /* middle part - process nodes with cardinality of 0..n */
4772 if (c_must) {
4773 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004774 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004776 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004777 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004778 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004779 }
Radek Krejcie534c132016-11-23 13:32:31 +01004780 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004781 /* some extensions may be already present from the substatements */
4782 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004783 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004784 retval->ext = reallocated;
4785
4786 /* init memory */
4787 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004788 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004789
Radek Krejcie534c132016-11-23 13:32:31 +01004790 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4791 if (strcmp(sub->ns->value, LY_NSYIN)) {
4792 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004793 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 +01004794 retval->ext_size++;
4795 if (r) {
4796 goto error;
4797 }
4798 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004799 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004800 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 if (r) {
4802 goto error;
4803 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004804 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004805 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004806 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004807 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004808 goto error;
4809 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004812
Radek Krejcicbb473e2016-09-16 14:48:32 +02004813 /* finalize type parsing */
4814 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4815 leaf->type.der = NULL;
4816 goto error;
4817 }
4818
4819 /* check default value (if not defined, there still could be some restrictions
4820 * that need to be checked against a default value from a derived type) */
Michal Vasko6a057782018-03-09 13:24:33 +01004821 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004822 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4823 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004824 goto error;
4825 }
4826
Michal Vasko508a50d2016-09-07 14:50:33 +02004827 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004828 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004829 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004830 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004831 goto error;
4832 }
4833 } else {
4834 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4835 goto error;
4836 }
4837 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004838 }
4839
PavolVican92f23622017-12-12 13:35:56 +01004840 for (r = 0; r < retval->ext_size; ++r) {
4841 /* set flag, which represent LYEXT_OPT_VALID */
4842 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004843 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004844 break;
4845 }
4846 }
4847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004848 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004849
4850error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004851 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004853}
4854
Michal Vasko0d343d12015-08-24 14:57:36 +02004855/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004856static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004857read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004858 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004859{
Michal Vasko53b7da02018-02-13 15:28:42 +01004860 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004861 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004862 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 struct lyxml_elem *sub, *next;
4864 const char *value;
4865 char *endptr;
4866 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004867 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004868 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004870 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004873 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004874
Radek Krejci76512572015-08-04 09:47:08 +02004875 llist->nodetype = LYS_LEAFLIST;
4876 llist->prev = (struct lys_node *)llist;
4877 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004878
Radek Krejci07d0fb92017-01-13 14:11:05 +01004879 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004880 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4881 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4882 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 goto error;
4884 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004885
Michal Vasko3e3228d2017-02-24 14:55:32 +01004886 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004887
Radek Krejcic189a952016-07-11 15:27:07 +02004888 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004889 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004890 goto error;
4891 }
4892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004893 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004894 if (strcmp(sub->ns->value, LY_NSYIN)) {
4895 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004896 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004897 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004898 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004899 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004900 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004901 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 goto error;
4903 }
Michal Vasko88c29542015-11-27 14:57:53 +01004904 /* HACK for unres */
4905 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004906 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004907 /* postpone type resolution when if-feature parsing is done since we need
4908 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004909 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004910 } else if (!strcmp(sub->name, "units")) {
4911 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004912 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004913 goto error;
4914 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004915 GETVAL(ctx, value, sub, "name");
4916 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004917
Radek Krejci8d6b7422017-02-03 14:42:13 +01004918 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004919 goto error;
4920 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 } else if (!strcmp(sub->name, "ordered-by")) {
4922 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004923 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 goto error;
4925 }
4926 /* just checking the flags in llist is not sufficient, we would
4927 * allow multiple ordered-by statements with the "system" value
4928 */
4929 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004930
Radek Krejci1574a8d2015-08-03 14:16:52 +02004931 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004932 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4933 * state data
4934 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004935 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 continue;
4937 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004938
Michal Vasko53b7da02018-02-13 15:28:42 +01004939 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004940 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004941 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004943 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004944 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004945 } /* else system is the default value, so we can ignore it */
4946
Radek Krejci8d6b7422017-02-03 14:42:13 +01004947 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004948 goto error;
4949 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004950 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004951 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004953 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004954 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004955 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004956 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004957 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004958 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004959 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004960 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 +01004961 goto error;
4962 }
4963
Michal Vasko53b7da02018-02-13 15:28:42 +01004964 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004965 c_dflt++;
4966 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004968 } else if (!strcmp(sub->name, "min-elements")) {
4969 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004970 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971 goto error;
4972 }
4973 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004974
Michal Vasko53b7da02018-02-13 15:28:42 +01004975 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 while (isspace(value[0])) {
4977 value++;
4978 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004980 /* convert it to uint32_t */
4981 errno = 0;
4982 endptr = NULL;
4983 val = strtoul(value, &endptr, 10);
4984 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004985 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 goto error;
4987 }
4988 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004989 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004990 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4991 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004992 goto error;
4993 }
Radek Krejci5323b492017-01-16 15:40:11 +01004994
Radek Krejci8d6b7422017-02-03 14:42:13 +01004995 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004996 goto error;
4997 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004998 } else if (!strcmp(sub->name, "max-elements")) {
4999 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005000 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 goto error;
5002 }
5003 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005004
Michal Vasko53b7da02018-02-13 15:28:42 +01005005 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 while (isspace(value[0])) {
5007 value++;
5008 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005009
Radek Krejci0d7b2472016-02-12 11:11:03 +01005010 if (!strcmp(value, "unbounded")) {
5011 llist->max = 0;
5012 } else {
5013 /* convert it to uint32_t */
5014 errno = 0;
5015 endptr = NULL;
5016 val = strtoul(value, &endptr, 10);
5017 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005018 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005019 goto error;
5020 }
5021 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005022 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005023 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5024 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005025 goto error;
5026 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 }
Radek Krejci5323b492017-01-16 15:40:11 +01005028
Radek Krejci8d6b7422017-02-03 14:42:13 +01005029 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005030 goto error;
5031 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005032 } else if (!strcmp(sub->name, "when")) {
5033 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005034 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005035 goto error;
5036 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005037
Radek Krejci5323b492017-01-16 15:40:11 +01005038 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005039 if (!llist->when) {
5040 goto error;
5041 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005042 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005043 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005045 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005046
Michal Vasko88c29542015-11-27 14:57:53 +01005047 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005048 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005051 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005052 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005053 goto error;
5054 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005056 /* middle part - process nodes with cardinality of 0..n */
5057 if (c_must) {
5058 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005059 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005060 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005061 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005062 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005063 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005064 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005065 if (c_dflt) {
5066 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005067 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005068 }
Radek Krejcie534c132016-11-23 13:32:31 +01005069 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005070 /* some extensions may be already present from the substatements */
5071 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005072 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005073 retval->ext = reallocated;
5074
5075 /* init memory */
5076 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005077 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005078
Radek Krejcie534c132016-11-23 13:32:31 +01005079 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5080 if (strcmp(sub->ns->value, LY_NSYIN)) {
5081 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005082 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 +01005083 retval->ext_size++;
5084 if (r) {
5085 goto error;
5086 }
5087 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005088 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005089 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005090 if (r) {
5091 goto error;
5092 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005093 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005094 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005095 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005096 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005097 goto error;
5098 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005099 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005100 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005101
Radek Krejciac1a52c2016-09-15 14:42:40 +02005102 /* check for duplicity in case of configuration data,
5103 * in case of status data duplicities are allowed */
5104 if (llist->flags & LYS_CONFIG_W) {
5105 for (r = 0; r < llist->dflt_size; r++) {
5106 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005107 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5108 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005109 goto error;
5110 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005111 }
5112 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005113 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005115 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005116
Radek Krejcicbb473e2016-09-16 14:48:32 +02005117 /* finalize type parsing */
5118 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5119 llist->type.der = NULL;
5120 goto error;
5121 }
5122
Radek Krejcid5a5c282016-08-15 15:38:08 +02005123 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005124 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5125 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005126 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5127 goto error;
5128 }
5129
5130 /* check default value (if not defined, there still could be some restrictions
5131 * that need to be checked against a default value from a derived type) */
5132 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko6a057782018-03-09 13:24:33 +01005133 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005134 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5135 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005136 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005137 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005138 }
5139
Michal Vasko508a50d2016-09-07 14:50:33 +02005140 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005141 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005142 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005143 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005144 goto error;
5145 }
5146 } else {
5147 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5148 goto error;
5149 }
5150 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005151 }
5152
PavolVican92f23622017-12-12 13:35:56 +01005153 for (r = 0; r < retval->ext_size; ++r) {
5154 /* set flag, which represent LYEXT_OPT_VALID */
5155 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005156 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005157 break;
5158 }
5159 }
5160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005162
5163error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005164 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005165 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005166}
5167
Michal Vasko0d343d12015-08-24 14:57:36 +02005168/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005169static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005170read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005171 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005172{
Michal Vasko53b7da02018-02-13 15:28:42 +01005173 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005174 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005175 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005177 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005178 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005179 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005180 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 char *auxs;
5182 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005183 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 /* init */
5186 memset(&root, 0, sizeof root);
5187 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005189 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005190 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005191
Radek Krejci76512572015-08-04 09:47:08 +02005192 list->nodetype = LYS_LIST;
5193 list->prev = (struct lys_node *)list;
5194 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005195
Radek Krejci07d0fb92017-01-13 14:11:05 +01005196 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005197 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5198 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5199 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 goto error;
5201 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005202
Michal Vasko3e3228d2017-02-24 14:55:32 +01005203 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005204
Radek Krejcic189a952016-07-11 15:27:07 +02005205 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005206 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005207 goto error;
5208 }
5209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005210 /* process list's specific children */
5211 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005212 if (strcmp(sub->ns->value, LY_NSYIN)) {
5213 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005214 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005215 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005216 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005218 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005219 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 !strcmp(sub->name, "leaf-list") ||
5221 !strcmp(sub->name, "leaf") ||
5222 !strcmp(sub->name, "list") ||
5223 !strcmp(sub->name, "choice") ||
5224 !strcmp(sub->name, "uses") ||
5225 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005226 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005227 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005228 !strcmp(sub->name, "action") ||
5229 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005230 lyxml_unlink_elem(ctx, sub, 2);
5231 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 /* array counters */
5234 } else if (!strcmp(sub->name, "key")) {
5235 /* check cardinality 0..1 */
5236 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005237 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005238 goto error;
5239 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005241 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005242 GETVAL(ctx, value, sub, "value");
5243 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005244 while ((value = strpbrk(value, " \t\n"))) {
5245 list->keys_size++;
5246 while (isspace(*value)) {
5247 value++;
5248 }
5249 }
5250 list->keys_size++;
5251 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005252 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005253
Radek Krejci8d6b7422017-02-03 14:42:13 +01005254 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005255 goto error;
5256 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005257 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005258 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005259 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005260 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005261 lyxml_unlink_elem(ctx, sub, 2);
5262 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005264 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005265 c_tpdf++;
5266 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005267 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005269 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005270 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005271 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 /* optional stetments */
5274 } else if (!strcmp(sub->name, "ordered-by")) {
5275 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005276 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 goto error;
5278 }
5279 /* just checking the flags in llist is not sufficient, we would
5280 * allow multiple ordered-by statements with the "system" value
5281 */
5282 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005283
Radek Krejci1574a8d2015-08-03 14:16:52 +02005284 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5286 * state data
5287 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005288 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 continue;
5290 }
Radek Krejci345ad742015-06-03 11:04:18 +02005291
Michal Vasko53b7da02018-02-13 15:28:42 +01005292 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005294 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005295 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005296 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005297 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005298 } /* else system is the default value, so we can ignore it */
5299
Radek Krejci8d6b7422017-02-03 14:42:13 +01005300 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005301 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005302 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005303 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005304 } else if (!strcmp(sub->name, "min-elements")) {
5305 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005306 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005307 goto error;
5308 }
5309 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005310
Michal Vasko53b7da02018-02-13 15:28:42 +01005311 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 while (isspace(value[0])) {
5313 value++;
5314 }
Radek Krejci345ad742015-06-03 11:04:18 +02005315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 /* convert it to uint32_t */
5317 errno = 0;
5318 auxs = NULL;
5319 val = strtoul(value, &auxs, 10);
5320 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005321 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005322 goto error;
5323 }
5324 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005325 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005326 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5327 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5328 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005329 goto error;
5330 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005331 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005332 goto error;
5333 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005334 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005335 } else if (!strcmp(sub->name, "max-elements")) {
5336 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005337 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005338 goto error;
5339 }
5340 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005341
Michal Vasko53b7da02018-02-13 15:28:42 +01005342 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005343 while (isspace(value[0])) {
5344 value++;
5345 }
Radek Krejci345ad742015-06-03 11:04:18 +02005346
Radek Krejci0d7b2472016-02-12 11:11:03 +01005347 if (!strcmp(value, "unbounded")) {
5348 list->max = 0;;
5349 } else {
5350 /* convert it to uint32_t */
5351 errno = 0;
5352 auxs = NULL;
5353 val = strtoul(value, &auxs, 10);
5354 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005355 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005356 goto error;
5357 }
5358 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005359 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005360 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5361 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005362 goto error;
5363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005364 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005365 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005366 goto error;
5367 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005368 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005369 } else if (!strcmp(sub->name, "when")) {
5370 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005371 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005372 goto error;
5373 }
5374
Radek Krejci5323b492017-01-16 15:40:11 +01005375 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005376 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005377 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005378 goto error;
5379 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005380 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005381 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005382 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005383 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005384 }
5385 }
Radek Krejci345ad742015-06-03 11:04:18 +02005386
Michal Vaskoe022a562016-09-27 14:24:15 +02005387 /* check - if list is configuration, key statement is mandatory
5388 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005389 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005390 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005391 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005392 goto error;
5393 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005395 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5396 if (c_tpdf) {
5397 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005398 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005399 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005400 if (c_must) {
5401 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005402 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005403 }
5404 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005405 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005406 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005407 }
Radek Krejcie534c132016-11-23 13:32:31 +01005408 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005409 /* some extensions may be already present from the substatements */
5410 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005411 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005412 retval->ext = reallocated;
5413
5414 /* init memory */
5415 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005416 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005417
Radek Krejcie534c132016-11-23 13:32:31 +01005418 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5419 if (strcmp(sub->ns->value, LY_NSYIN)) {
5420 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005421 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 +01005422 retval->ext_size++;
5423 if (r) {
5424 goto error;
5425 }
5426 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005427 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5428 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005429 if (r) {
5430 goto error;
5431 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005432 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005433 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005434 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005435 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005436 goto error;
5437 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005438 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005439 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005440 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005441 if (r) {
5442 goto error;
5443 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005444 }
5445 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005447 /* last part - process data nodes */
5448 LY_TREE_FOR_SAFE(root.child, next, sub) {
5449 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005450 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005451 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005452 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005454 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005455 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005456 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005457 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005458 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005459 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005460 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005461 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005462 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005463 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005464 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005465 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005466 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005467 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005468 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005469 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005470 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005471 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005472 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005473 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005474 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005475 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 goto error;
5477 }
Radek Krejci73adb602015-07-02 18:07:40 +02005478
Michal Vasko53b7da02018-02-13 15:28:42 +01005479 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005480 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005481
Radek Krejci5c08a992016-11-02 13:30:04 +01005482 if (list->keys_str) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02005483 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005484 goto error;
5485 }
5486 } /* 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 +02005487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005488 /* process unique statements */
5489 if (c_uniq) {
5490 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005491 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005492
Radek Krejci461efb92016-02-12 15:52:18 +01005493 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5494 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5495 list->unique_size++;
5496 if (r) {
5497 goto error;
5498 }
5499
Radek Krejci8d6b7422017-02-03 14:42:13 +01005500 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005501 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5502 goto error;
5503 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005504 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005505 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005506 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005507
Michal Vasko508a50d2016-09-07 14:50:33 +02005508 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005509 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005510 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005511 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005512 goto error;
5513 }
5514 } else {
5515 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5516 goto error;
5517 }
5518 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005519 }
5520
PavolVican92f23622017-12-12 13:35:56 +01005521 for (r = 0; r < retval->ext_size; ++r) {
5522 /* set flag, which represent LYEXT_OPT_VALID */
5523 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005524 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005525 break;
5526 }
5527 }
5528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005530
5531error:
5532
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005533 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005534 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005535 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005536 }
5537 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005538 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005539 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005541 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005542}
5543
Michal Vasko0d343d12015-08-24 14:57:36 +02005544/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005545static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005546read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005547 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005548{
Michal Vasko53b7da02018-02-13 15:28:42 +01005549 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005550 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005551 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005552 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005553 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005554 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005555 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005556 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005557 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005559 /* init */
5560 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005563 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005564
Radek Krejci76512572015-08-04 09:47:08 +02005565 cont->nodetype = LYS_CONTAINER;
5566 cont->prev = (struct lys_node *)cont;
5567 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005568
Radek Krejci07d0fb92017-01-13 14:11:05 +01005569 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005570 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5571 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5572 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005573 goto error;
5574 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005575
Michal Vasko3e3228d2017-02-24 14:55:32 +01005576 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005577
Radek Krejcic189a952016-07-11 15:27:07 +02005578 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005579 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005580 goto error;
5581 }
5582
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005583 /* process container's specific children */
5584 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005585 if (strcmp(sub->ns->value, LY_NSYIN)) {
5586 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005587 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005588 c_ext++;
5589 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005590 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005591 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005592 goto error;
5593 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005594 GETVAL(ctx, value, sub, "value");
5595 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005596
Radek Krejci8d6b7422017-02-03 14:42:13 +01005597 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005598 goto error;
5599 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005600 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005601 } else if (!strcmp(sub->name, "when")) {
5602 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005603 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005604 goto error;
5605 }
5606
Radek Krejci5323b492017-01-16 15:40:11 +01005607 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005608 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005609 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005610 goto error;
5611 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005612 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 /* data statements */
5615 } else if (!strcmp(sub->name, "container") ||
5616 !strcmp(sub->name, "leaf-list") ||
5617 !strcmp(sub->name, "leaf") ||
5618 !strcmp(sub->name, "list") ||
5619 !strcmp(sub->name, "choice") ||
5620 !strcmp(sub->name, "uses") ||
5621 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005622 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005623 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005624 !strcmp(sub->name, "action") ||
5625 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005626 lyxml_unlink_elem(ctx, sub, 2);
5627 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005629 /* array counters */
5630 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005631 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005632 c_tpdf++;
5633 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005634 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005635 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005636 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005637 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005638 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005639 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005640 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005641 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005642 }
5643 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005644
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005645 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5646 if (c_tpdf) {
5647 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005648 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005649 }
5650 if (c_must) {
5651 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005652 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005653 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005654 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005655 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005656 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005657 }
Radek Krejcie534c132016-11-23 13:32:31 +01005658 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005659 /* some extensions may be already present from the substatements */
5660 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005661 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005662 retval->ext = reallocated;
5663
5664 /* init memory */
5665 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005666 }
Radek Krejci800af702015-06-02 13:46:01 +02005667
Radek Krejcie534c132016-11-23 13:32:31 +01005668 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5669 if (strcmp(sub->ns->value, LY_NSYIN)) {
5670 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005671 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 +01005672 retval->ext_size++;
5673 if (r) {
5674 goto error;
5675 }
5676 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005677 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5678 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005679 if (r) {
5680 goto error;
5681 }
5682 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005683 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005684 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005685 if (r) {
5686 goto error;
5687 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005688 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005689 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005690 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005691 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005692 goto error;
5693 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005694 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005695 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005697 /* last part - process data nodes */
5698 LY_TREE_FOR_SAFE(root.child, next, sub) {
5699 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005700 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005701 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005702 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005703 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005704 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005705 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005706 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005707 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005708 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005709 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005710 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005711 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005712 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005713 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005714 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005715 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005716 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005717 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005718 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005719 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005720 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005721 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005722 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005723 goto error;
5724 }
Radek Krejci73adb602015-07-02 18:07:40 +02005725
Michal Vasko53b7da02018-02-13 15:28:42 +01005726 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005727 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005728
Michal Vasko508a50d2016-09-07 14:50:33 +02005729 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005730 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005731 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005732 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005733 goto error;
5734 }
5735 } else {
5736 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5737 goto error;
5738 }
5739 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005740 }
5741
PavolVican92f23622017-12-12 13:35:56 +01005742 for (r = 0; r < retval->ext_size; ++r) {
5743 /* set flag, which represent LYEXT_OPT_VALID */
5744 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005745 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005746 break;
5747 }
5748 }
5749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005750 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005751
5752error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005753 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005754 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005755 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005756 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005757 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005758}
5759
Michal Vasko0d343d12015-08-24 14:57:36 +02005760/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005761static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005762read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005763 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005764{
Michal Vasko53b7da02018-02-13 15:28:42 +01005765 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005766 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005767 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005768 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005769 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005770 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005771 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005772 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005774 /* init */
5775 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005777 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005778 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005779
Radek Krejci76512572015-08-04 09:47:08 +02005780 grp->nodetype = LYS_GROUPING;
5781 grp->prev = (struct lys_node *)grp;
5782 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005783
Radek Krejci07d0fb92017-01-13 14:11:05 +01005784 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005785 goto error;
5786 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005787
Michal Vasko3e3228d2017-02-24 14:55:32 +01005788 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005789
Radek Krejcic189a952016-07-11 15:27:07 +02005790 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005791 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005792 goto error;
5793 }
5794
Radek Krejci1d82ef62015-08-07 14:44:40 +02005795 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005796 if (strcmp(sub->ns->value, LY_NSYIN)) {
5797 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005798 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005799 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005801 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005802 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005803 !strcmp(sub->name, "leaf-list") ||
5804 !strcmp(sub->name, "leaf") ||
5805 !strcmp(sub->name, "list") ||
5806 !strcmp(sub->name, "choice") ||
5807 !strcmp(sub->name, "uses") ||
5808 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005809 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005810 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005811 !strcmp(sub->name, "action") ||
5812 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005813 lyxml_unlink_elem(ctx, sub, 2);
5814 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005816 /* array counters */
5817 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005818 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005819 c_tpdf++;
5820 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005821 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005822 goto error;
5823 }
5824 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005826 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5827 if (c_tpdf) {
5828 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005829 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005830 }
Radek Krejcie534c132016-11-23 13:32:31 +01005831 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005832 /* some extensions may be already present from the substatements */
5833 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005834 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005835 retval->ext = reallocated;
5836
5837 /* init memory */
5838 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005839 }
Radek Krejcie534c132016-11-23 13:32:31 +01005840 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5841 if (strcmp(sub->ns->value, LY_NSYIN)) {
5842 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005843 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 +01005844 retval->ext_size++;
5845 if (r) {
5846 goto error;
5847 }
5848 } else {
5849 /* typedef */
5850 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5851 grp->tpdf_size++;
5852 if (r) {
5853 goto error;
5854 }
5855 }
5856 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005858 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005859 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005860 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005861 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005862 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005863 LY_TREE_FOR_SAFE(root.child, next, sub) {
5864 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005865 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005866 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005867 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005868 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005869 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005870 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005871 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005872 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005873 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005874 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005875 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005876 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005877 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005878 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005879 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005880 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005881 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005882 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005883 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005884 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005885 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005886 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005887 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005888 goto error;
5889 }
Radek Krejci73adb602015-07-02 18:07:40 +02005890
Michal Vasko53b7da02018-02-13 15:28:42 +01005891 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005892 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005893
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005894 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005895
5896error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005897 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005898 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005899 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005900 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005901 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005902}
5903
Michal Vasko0d343d12015-08-24 14:57:36 +02005904/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005905static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005906read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005907 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005908{
Michal Vasko53b7da02018-02-13 15:28:42 +01005909 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005910 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005911 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005912 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005913 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005914 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005915 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005916
Radek Krejcie0674f82015-06-15 13:58:51 +02005917 /* init */
5918 memset(&root, 0, sizeof root);
5919
Michal Vasko38d01f72015-06-15 09:41:06 +02005920 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005921 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005922 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005923
5924 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005925 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005926 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005927 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005928 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005929 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005930 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005931 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005932 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005933 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005934 }
5935
Radek Krejci76512572015-08-04 09:47:08 +02005936 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005937 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005938
Michal Vasko3e3228d2017-02-24 14:55:32 +01005939 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005940
Radek Krejcic189a952016-07-11 15:27:07 +02005941 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005942 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005943 goto error;
5944 }
5945
Michal Vasko38d01f72015-06-15 09:41:06 +02005946 /* data statements */
5947 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005948 if (!sub->ns) {
5949 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005950 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005951 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005952 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005953 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005954 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005955 c_ext++;
5956 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005957 !strcmp(sub->name, "leaf-list") ||
5958 !strcmp(sub->name, "leaf") ||
5959 !strcmp(sub->name, "list") ||
5960 !strcmp(sub->name, "choice") ||
5961 !strcmp(sub->name, "uses") ||
5962 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005963 !strcmp(sub->name, "anyxml") ||
5964 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005965 lyxml_unlink_elem(ctx, sub, 2);
5966 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005968 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005969 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005970 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02005971 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005972 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005973
Radek Krejci1a31efe2016-07-29 11:04:16 +02005974 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005975 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02005976 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02005977 c_must++;
5978
Michal Vasko38d01f72015-06-15 09:41:06 +02005979 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005980 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005981 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005982 }
5983 }
5984
5985 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5986 if (c_tpdf) {
5987 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005988 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005989 }
Radek Krejci19332802016-07-29 10:39:46 +02005990 if (c_must) {
5991 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005992 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02005993 }
Radek Krejcie534c132016-11-23 13:32:31 +01005994 if (c_ext) {
5995 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005996 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01005997 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005998
Radek Krejcie534c132016-11-23 13:32:31 +01005999 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6000 if (strcmp(sub->ns->value, LY_NSYIN)) {
6001 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006002 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 +01006003 retval->ext_size++;
6004 if (r) {
6005 goto error;
6006 }
6007 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006008 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006009 inout->must_size++;
6010 if (r) {
6011 goto error;
6012 }
6013 } else { /* typedef */
6014 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
6015 inout->tpdf_size++;
6016 if (r) {
6017 goto error;
6018 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006019 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006020 }
6021
6022 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006023 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02006024 LY_TREE_FOR_SAFE(root.child, next, sub) {
6025 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006026 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006027 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006028 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006029 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006030 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006031 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006032 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006033 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006034 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006035 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006036 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006037 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006038 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006039 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006040 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006041 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006042 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006043 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006044 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006045 goto error;
6046 }
Radek Krejci73adb602015-07-02 18:07:40 +02006047
Michal Vasko53b7da02018-02-13 15:28:42 +01006048 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006049 }
6050
Michal Vasko508a50d2016-09-07 14:50:33 +02006051 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006052 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006053 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006054 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006055 goto error;
6056 }
6057 } else {
6058 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6059 goto error;
6060 }
6061 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006062 }
6063
Michal Vasko38d01f72015-06-15 09:41:06 +02006064 return retval;
6065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006066error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006067 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006068 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006069 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006070 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006071 return NULL;
6072}
6073
Michal Vasko0d343d12015-08-24 14:57:36 +02006074/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006075static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006076read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006077 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006078{
Michal Vasko53b7da02018-02-13 15:28:42 +01006079 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006080 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006081 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006082 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006083 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006084 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006085 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006086 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006087
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006088 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006089 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006090 return NULL;
6091 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006092
Michal Vaskoc6551b32015-06-16 10:51:43 +02006093 memset(&root, 0, sizeof root);
6094
Michal Vasko0ea41032015-06-16 08:53:55 +02006095 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006096 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006097
Radek Krejci76512572015-08-04 09:47:08 +02006098 notif->nodetype = LYS_NOTIF;
6099 notif->prev = (struct lys_node *)notif;
6100 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006101
Radek Krejci07d0fb92017-01-13 14:11:05 +01006102 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006103 goto error;
6104 }
6105
Michal Vasko3e3228d2017-02-24 14:55:32 +01006106 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006107
Radek Krejcic189a952016-07-11 15:27:07 +02006108 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006109 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006110 goto error;
6111 }
6112
Michal Vasko0ea41032015-06-16 08:53:55 +02006113 /* process rpc's specific children */
6114 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006115 if (strcmp(sub->ns->value, LY_NSYIN)) {
6116 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006117 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006118 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006119 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006120
Michal Vasko0ea41032015-06-16 08:53:55 +02006121 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006122 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006123 !strcmp(sub->name, "leaf-list") ||
6124 !strcmp(sub->name, "leaf") ||
6125 !strcmp(sub->name, "list") ||
6126 !strcmp(sub->name, "choice") ||
6127 !strcmp(sub->name, "uses") ||
6128 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006129 !strcmp(sub->name, "anyxml") ||
6130 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006131 lyxml_unlink_elem(ctx, sub, 2);
6132 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006134 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006135 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006136 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006137 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006138 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006139 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006140 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006141 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006142 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006143 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006144 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006145 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006146 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006147 }
6148 }
6149
6150 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6151 if (c_tpdf) {
6152 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006153 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006154 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006155 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006156 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006157 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006158 }
Radek Krejci19332802016-07-29 10:39:46 +02006159 if (c_must) {
6160 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006161 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006162 }
Radek Krejcie534c132016-11-23 13:32:31 +01006163 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006164 /* some extensions may be already present from the substatements */
6165 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006166 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006167 retval->ext = reallocated;
6168
6169 /* init memory */
6170 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006171 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006172
Radek Krejcie534c132016-11-23 13:32:31 +01006173 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6174 if (strcmp(sub->ns->value, LY_NSYIN)) {
6175 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006176 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 +01006177 retval->ext_size++;
6178 if (r) {
6179 goto error;
6180 }
6181 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006182 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6183 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006184 if (r) {
6185 goto error;
6186 }
Radek Krejci96299152016-06-22 10:17:50 +02006187 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006188 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006189 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006190 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006191 goto error;
6192 }
Radek Krejci19332802016-07-29 10:39:46 +02006193 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006194 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006195 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006196 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006197 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006198 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006199 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006200 }
6201
6202 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006203 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006204 LY_TREE_FOR_SAFE(root.child, next, sub) {
6205 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006206 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006207 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006208 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006209 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006210 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006211 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006212 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006213 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006214 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006215 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006216 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006217 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006218 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006219 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006220 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006221 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006222 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006223 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006224 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006225 goto error;
6226 }
Radek Krejci73adb602015-07-02 18:07:40 +02006227
Michal Vasko53b7da02018-02-13 15:28:42 +01006228 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006229 }
6230
Michal Vasko508a50d2016-09-07 14:50:33 +02006231 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006232 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006233 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006234 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006235 goto error;
6236 }
6237 } else {
6238 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6239 goto error;
6240 }
6241 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006242 }
6243
Michal Vasko0ea41032015-06-16 08:53:55 +02006244 return retval;
6245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006246error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006247 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006248 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006249 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006250 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006251 return NULL;
6252}
6253
Michal Vasko0d343d12015-08-24 14:57:36 +02006254/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006255static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006256read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006257 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006258{
Michal Vasko53b7da02018-02-13 15:28:42 +01006259 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006260 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006261 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006262 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006263 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006264 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006265 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006266 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006267
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006268 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006269 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006270 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006271 return NULL;
6272 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006273 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006274 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006275 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006276 LOGVAL(ctx, LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006277 return NULL;
6278 }
6279 }
6280 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006281
Radek Krejcie0674f82015-06-15 13:58:51 +02006282 /* init */
6283 memset(&root, 0, sizeof root);
6284
Michal Vasko38d01f72015-06-15 09:41:06 +02006285 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006286 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006287
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006288 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006289 rpc->prev = (struct lys_node *)rpc;
6290 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006291
Radek Krejci07d0fb92017-01-13 14:11:05 +01006292 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006293 goto error;
6294 }
6295
Michal Vasko3e3228d2017-02-24 14:55:32 +01006296 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006297
Radek Krejcic189a952016-07-11 15:27:07 +02006298 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006299 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006300 goto error;
6301 }
6302
Michal Vasko38d01f72015-06-15 09:41:06 +02006303 /* process rpc's specific children */
6304 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006305 if (strcmp(sub->ns->value, LY_NSYIN)) {
6306 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006307 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006308 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006309 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006310 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006311 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006312 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006313 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006314 goto error;
6315 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006316 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006317 lyxml_unlink_elem(ctx, sub, 2);
6318 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006319 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006320 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006321 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006322 goto error;
6323 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006324 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006325 lyxml_unlink_elem(ctx, sub, 2);
6326 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006328 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006329 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006330 lyxml_unlink_elem(ctx, sub, 2);
6331 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006333 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006334 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006335 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006336 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006337 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006338 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006339 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006340 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006341 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006342 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006343 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006344 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006345 }
6346 }
6347
6348 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6349 if (c_tpdf) {
6350 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006351 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006352 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006353 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006354 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006355 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006356 }
Radek Krejcie534c132016-11-23 13:32:31 +01006357 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006358 /* some extensions may be already present from the substatements */
6359 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006360 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006361 retval->ext = reallocated;
6362
6363 /* init memory */
6364 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006365 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006366
Radek Krejcie534c132016-11-23 13:32:31 +01006367 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6368 if (strcmp(sub->ns->value, LY_NSYIN)) {
6369 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006370 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 +01006371 retval->ext_size++;
6372 if (r) {
6373 goto error;
6374 }
6375 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006376 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6377 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006378 if (r) {
6379 goto error;
6380 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006381 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006382 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006383 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006384 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006385 goto error;
6386 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006387 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006388 }
6389
6390 /* last part - process data nodes */
6391 LY_TREE_FOR_SAFE(root.child, next, sub) {
6392 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006393 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006394 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006395 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006396 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006397 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006398 goto error;
6399 }
Radek Krejci73adb602015-07-02 18:07:40 +02006400
Michal Vasko53b7da02018-02-13 15:28:42 +01006401 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006402 }
6403
Michal Vasko38d01f72015-06-15 09:41:06 +02006404 return retval;
6405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006406error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006407 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006408 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006409 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006410 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006411 return NULL;
6412}
6413
Michal Vasko0d343d12015-08-24 14:57:36 +02006414/* logs directly
6415 *
Radek Krejci74705112015-06-05 10:25:44 +02006416 * resolve - referenced grouping should be bounded to the namespace (resolved)
6417 * only when uses does not appear in grouping. In a case of grouping's uses,
6418 * we just get information but we do not apply augment or refine to it.
6419 */
Radek Krejci76512572015-08-04 09:47:08 +02006420static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006421read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6422 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006423{
Michal Vasko53b7da02018-02-13 15:28:42 +01006424 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006425 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006426 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006427 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006428 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006429 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006430 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006431 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006433 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006434 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006435
Radek Krejci76512572015-08-04 09:47:08 +02006436 uses->nodetype = LYS_USES;
6437 uses->prev = (struct lys_node *)uses;
6438 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006439
Michal Vasko53b7da02018-02-13 15:28:42 +01006440 GETVAL(ctx, value, yin, "name");
6441 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006442
Radek Krejci07d0fb92017-01-13 14:11:05 +01006443 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006444 goto error;
6445 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006446
Michal Vasko3e3228d2017-02-24 14:55:32 +01006447 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006448
Radek Krejcic189a952016-07-11 15:27:07 +02006449 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006450 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006451 goto error;
6452 }
6453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006454 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006455 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006456 if (strcmp(sub->ns->value, LY_NSYIN)) {
6457 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006458 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006459 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006460 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006461 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006462 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006463 c_ref++;
6464 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006465 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006466 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006467 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006468 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006469 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006470 } else if (!strcmp(sub->name, "when")) {
6471 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006472 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006473 goto error;
6474 }
6475
Radek Krejci5323b492017-01-16 15:40:11 +01006476 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006477 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006478 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006479 goto error;
6480 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006481 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006482 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006483 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006484 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006485 }
6486 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006488 /* process properties with cardinality 0..n */
6489 if (c_ref) {
6490 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006491 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006492 }
6493 if (c_aug) {
6494 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006495 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006496 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006497 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006498 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006499 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006500 }
Radek Krejcie534c132016-11-23 13:32:31 +01006501 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006502 /* some extensions may be already present from the substatements */
6503 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006504 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006505 retval->ext = reallocated;
6506
6507 /* init memory */
6508 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006509 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006510
Radek Krejcie534c132016-11-23 13:32:31 +01006511 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6512 if (strcmp(sub->ns->value, LY_NSYIN)) {
6513 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006514 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 +01006515 retval->ext_size++;
6516 if (r) {
6517 goto error;
6518 }
6519 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006520 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006521 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006522 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006523 goto error;
6524 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006525 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006526 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006527 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006528 if (r) {
6529 goto error;
6530 }
6531 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006532 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006533 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006534 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006535 goto error;
6536 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006537 }
6538 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006539
Radek Krejci48464ed2016-03-17 15:44:09 +01006540 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006541 goto error;
6542 }
Radek Krejci74705112015-06-05 10:25:44 +02006543
Michal Vasko508a50d2016-09-07 14:50:33 +02006544 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006545 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006546 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006547 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006548 goto error;
6549 }
6550 } else {
6551 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6552 goto error;
6553 }
6554 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006555 }
6556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006557 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006558
6559error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006560 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006561 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006562}
6563
Michal Vasko0d343d12015-08-24 14:57:36 +02006564/* logs directly
6565 *
6566 * common code for yin_read_module() and yin_read_submodule()
6567 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006568static int
Radek Krejcic071c542016-01-27 14:57:51 +01006569read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6570 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006571{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006572 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006573 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006574 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006575 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006576 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006577 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006578 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006579 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6580 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6581 int substmt_group;
6582 /* just remember last substatement for logging */
6583 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006584 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006585 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;
6586 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006587 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006588
Radek Krejcic071c542016-01-27 14:57:51 +01006589 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006590 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006592 /* init */
6593 memset(&root, 0, sizeof root);
6594 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006595 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006596 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006597 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006599 /*
6600 * in the first run, we process elements with cardinality of 1 or 0..1 and
6601 * count elements with cardinality 0..n. Data elements (choices, containers,
6602 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6603 * need have all top-level and groupings already prepared at that time. In
6604 * the middle loop, we process other elements with carinality of 0..n since
6605 * we need to allocate arrays to store them.
6606 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006607 substmt_group = 0;
6608 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006609 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006610 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006611 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006612 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006613 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006614 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006615 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006616 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006617 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006618 lyxml_unlink_elem(ctx, child, 2);
6619 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006620 c_extinst++;
6621 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006622 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006623 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6624 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006625 child->name, substmt_prev);
6626 goto error;
6627 }
6628
PavolVican9e81c6a2017-02-09 13:09:07 +01006629 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006630 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006631 goto error;
6632 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006633 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006634 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006635
Radek Krejci8d6b7422017-02-03 14:42:13 +01006636 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006637 goto error;
6638 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006639 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006640
6641 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006642 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006643 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006644 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6645 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006646 child->name, substmt_prev);
6647 goto error;
6648 }
6649
PavolVican9e81c6a2017-02-09 13:09:07 +01006650 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006651 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006652 goto error;
6653 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006654 GETVAL(ctx, value, child, "value");
6655 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006656 goto error;
6657 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006658 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006659
Radek Krejci8d6b7422017-02-03 14:42:13 +01006660 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006661 goto error;
6662 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006663 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006664
6665 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006666 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006667 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006668 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6669 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006670 child->name, substmt_prev);
6671 goto error;
6672 }
6673
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006674 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006675 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006676 goto error;
6677 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006678 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006679 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006680 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006681 goto error;
6682 }
Radek Krejcif3886932015-06-04 17:36:06 +02006683
Radek Krejci8d6b7422017-02-03 14:42:13 +01006684 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006685 goto error;
6686 }
6687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006688 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006689 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006690 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006691 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006692 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006693 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006694 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006695 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006696 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006697 goto error;
6698 }
6699 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006700 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006701 /* check here differs from a generic prefix check, since this prefix
6702 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006703 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006704 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006705 goto error;
6706 }
Radek Krejcic071c542016-01-27 14:57:51 +01006707 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006708
Radek Krejci8d6b7422017-02-03 14:42:13 +01006709 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 +01006710 goto error;
6711 }
6712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006713 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006714 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006715
Michal Vasko5de8a022017-02-08 10:57:26 +01006716 substmt_prev = "belongs-to";
6717
Radek Krejcieb00f512015-07-01 16:44:58 +02006718 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006719 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006720 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006721 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6722 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006723 child->name, substmt_prev);
6724 goto error;
6725 }
6726 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006727 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006728 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006729 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006730
6731 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006732 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006733 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006734 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6735 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006736 child->name, substmt_prev);
6737 goto error;
6738 }
6739 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006740 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006741 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006742 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006743
PavolVican9e81c6a2017-02-09 13:09:07 +01006744 lyxml_unlink_elem(ctx, child, 2);
6745 lyxml_add_child(ctx, &revs, child);
6746
Michal Vasko5de8a022017-02-08 10:57:26 +01006747 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006748 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006749 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006750 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006751 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006752 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006753
6754 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006755 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006756 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006757 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006758 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006759 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006760
6761 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006762 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006763 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006764 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6765 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006766 child->name, substmt_prev);
6767 goto error;
6768 }
6769 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006770 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006771 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006772 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006773
6774 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006775 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006776 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006777 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006778 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006779 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006780 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006781 lyxml_unlink_elem(ctx, child, 2);
6782 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006783
Michal Vasko5de8a022017-02-08 10:57:26 +01006784 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006785 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006786 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006787 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006788 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006789 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006790
Michal Vasko5de8a022017-02-08 10:57:26 +01006791 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006793 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006794 } else if (!strcmp(child->name, "container") ||
6795 !strcmp(child->name, "leaf-list") ||
6796 !strcmp(child->name, "leaf") ||
6797 !strcmp(child->name, "list") ||
6798 !strcmp(child->name, "choice") ||
6799 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006800 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006801 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006802 !strcmp(child->name, "rpc") ||
6803 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006804 substmt_group = 4;
6805
Radek Krejcic071c542016-01-27 14:57:51 +01006806 lyxml_unlink_elem(ctx, child, 2);
6807 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006808
Michal Vasko5de8a022017-02-08 10:57:26 +01006809 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006810 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006811 substmt_group = 4;
6812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006813 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006814 lyxml_unlink_elem(ctx, child, 2);
6815 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006816
Michal Vasko5de8a022017-02-08 10:57:26 +01006817 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006818 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006819 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006820 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006821 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6822 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006823 child->name, substmt_prev);
6824 goto error;
6825 }
6826 substmt_group = 2;
6827
Radek Krejcic071c542016-01-27 14:57:51 +01006828 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006829 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006830 goto error;
6831 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006832 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006833 goto error;
6834 }
Radek Krejcic071c542016-01-27 14:57:51 +01006835 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006836 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006837 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006838 goto error;
6839 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006840
6841 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006842 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006843 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006844 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6845 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006846 child->name, substmt_prev);
6847 goto error;
6848 }
6849 substmt_group = 2;
6850
Radek Krejcic071c542016-01-27 14:57:51 +01006851 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006852 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006853 goto error;
6854 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006855 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006856 goto error;
6857 }
Radek Krejcic071c542016-01-27 14:57:51 +01006858 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006859 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006860 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006861 goto error;
6862 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006863
6864 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006865 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006866 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006867 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6868 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006869 child->name, substmt_prev);
6870 goto error;
6871 }
6872 substmt_group = 2;
6873
Radek Krejcic071c542016-01-27 14:57:51 +01006874 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006875 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006876 goto error;
6877 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006878 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006879 goto error;
6880 }
Radek Krejcic071c542016-01-27 14:57:51 +01006881 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006882 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006883 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006884 goto error;
6885 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006886
6887 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006888 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006889 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006890 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6891 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006892 child->name, substmt_prev);
6893 goto error;
6894 }
6895 substmt_group = 2;
6896
Radek Krejcic071c542016-01-27 14:57:51 +01006897 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006898 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006899 goto error;
6900 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006901 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006902 goto error;
6903 }
Radek Krejcic071c542016-01-27 14:57:51 +01006904 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006905 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006906 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006907 goto error;
6908 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006909
6910 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006911 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006912 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006913 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6914 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006915 child->name, substmt_prev);
6916 goto error;
6917 }
6918
Radek Krejcic071c542016-01-27 14:57:51 +01006919 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006920 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006921 goto error;
6922 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006923 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006924 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006925 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006926 goto error;
6927 }
Radek Krejcic071c542016-01-27 14:57:51 +01006928 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006929 if (!strcmp(value, "1")) {
6930 if (submodule) {
6931 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006932 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006933 goto error;
6934 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006935 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006936 } else {
6937 module->version = 1;
6938 }
6939 } else {
6940 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006941 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006942 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006943 goto error;
6944 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006945 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006946 } else {
6947 module->version = 2;
6948 }
6949 }
6950
Radek Krejci8d6b7422017-02-03 14:42:13 +01006951 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006952 goto error;
6953 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006954 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006955
Michal Vasko5de8a022017-02-08 10:57:26 +01006956 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006957 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006958 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006959 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006960 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006961 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006962
Michal Vasko5de8a022017-02-08 10:57:26 +01006963 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006964 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006965 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006966 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006967 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006968 c_dev++;
6969
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006970 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006971 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006972 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006973 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006974 }
6975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006976
Radek Krejcic071c542016-01-27 14:57:51 +01006977 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006978 if (submodule) {
6979 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006980 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006981 goto error;
6982 }
6983 if (!version_flag) {
6984 /* check version compatibility with the main module */
6985 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006986 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006987 goto error;
6988 }
6989 }
6990 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006991 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006992 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006993 goto error;
6994 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006995 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006996 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006997 goto error;
6998 }
6999 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02007000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007001 /* allocate arrays for elements with cardinality of 0..n */
7002 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007003 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01007004 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007005 }
7006 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007007 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01007008 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007009 }
7010 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01007011 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01007012 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007013 }
7014 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01007015 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01007016 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007017 }
7018 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007019 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01007020 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007021 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007022 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01007023 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01007024 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007025 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02007026 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01007027 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007028 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007029 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007030 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007031 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007032 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007033 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007034 if (c_ext) {
7035 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007036 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007037 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007038
PavolVican9e81c6a2017-02-09 13:09:07 +01007039 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7040 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007041 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7042 trg->rev_size++;
7043 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007044 goto error;
7045 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007046
Radek Krejci7417a082017-02-16 11:07:59 +01007047 /* check uniqueness of the revision date - not required by RFC */
7048 for (i = 0; i < (trg->rev_size - 1); i++) {
7049 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007050 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007051 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007052 }
7053 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007054
7055 lyxml_free(ctx, child);
7056 }
7057
7058 /* check the module with respect to the context now */
7059 if (!submodule) {
7060 switch (lyp_ctx_check_module(module)) {
7061 case -1:
7062 goto error;
7063 case 0:
7064 break;
7065 case 1:
7066 /* it's already there */
7067 ret = 1;
7068 goto error;
7069 }
7070 }
7071
PavolVican92f23622017-12-12 13:35:56 +01007072 /* check first definition of extensions */
7073 if (c_ext) {
7074 LY_TREE_FOR_SAFE(yin->child, next, child) {
7075 if (!strcmp(child->name, "extension")) {
7076 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7077 trg->extensions_size++;
7078 if (r) {
7079 goto error;
7080 }
7081
7082 }
7083 }
7084 }
7085
PavolVican9e81c6a2017-02-09 13:09:07 +01007086 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007087 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007088 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007089 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007090 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007091 if (r) {
7092 goto error;
7093 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007094
Radek Krejci1d82ef62015-08-07 14:44:40 +02007095 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007096 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7097 trg->inc_size++;
7098 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007099 goto error;
7100 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007101
Radek Krejci1d82ef62015-08-07 14:44:40 +02007102 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007103 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7104 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007105 if (r) {
7106 goto error;
7107 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007108
Radek Krejci1d82ef62015-08-07 14:44:40 +02007109 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007110 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7111 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007112 if (r) {
7113 goto error;
7114 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007115
Radek Krejci1d82ef62015-08-07 14:44:40 +02007116 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007117 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7118 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007119 if (r) {
7120 goto error;
7121 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007122
Radek Krejci1d82ef62015-08-07 14:44:40 +02007123 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko0f437062018-06-08 15:52:39 +02007124 /* must be implemented in this case */
7125 trg->implemented = 1;
7126
Radek Krejcic071c542016-01-27 14:57:51 +01007127 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7128 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007129 if (r) {
7130 goto error;
7131 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007132 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007133 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007134
Radek Krejcie534c132016-11-23 13:32:31 +01007135 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007136 if (c_extinst) {
7137 /* some extensions may be already present from the substatements */
7138 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007139 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007140 trg->ext = reallocated;
7141
7142 /* init memory */
7143 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7144
7145 LY_TREE_FOR_SAFE(exts.child, next, child) {
7146 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7147 trg->ext_size++;
7148 if (r) {
7149 goto error;
7150 }
7151 }
Radek Krejcie534c132016-11-23 13:32:31 +01007152 }
7153
Radek Krejcif5be10f2015-06-16 13:29:36 +02007154 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007155 * refer to them. Submodule's data nodes are stored in the
7156 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007157 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007158 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007159 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007160 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007161 goto error;
7162 }
Radek Krejci74705112015-06-05 10:25:44 +02007163
Michal Vasko345da0a2015-12-02 10:35:55 +01007164 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007165 }
Radek Krejci74705112015-06-05 10:25:44 +02007166
Radek Krejcif5be10f2015-06-16 13:29:36 +02007167 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007168 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007169
Radek Krejci1d82ef62015-08-07 14:44:40 +02007170 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007171 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007172 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007173 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007174 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007175 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007176 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007177 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007178 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007179 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007180 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007181 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007182 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007183 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007184 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007185 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007186 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007187 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007188 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007189 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007190 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007191 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007192 goto error;
7193 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007194
Michal Vasko345da0a2015-12-02 10:35:55 +01007195 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007196 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007197
Michal Vasko2f7925f2015-10-21 15:06:56 +02007198 /* ... and finally augments (last, so we can augment our data, for instance) */
7199 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007200 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007201 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007202
Michal Vasko2f7925f2015-10-21 15:06:56 +02007203 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007204 goto error;
7205 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007206 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007207 }
7208
PavolVican9e81c6a2017-02-09 13:09:07 +01007209 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007210
7211error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007212 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007213 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007214 }
7215 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007216 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007217 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007218 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007219 lyxml_free(ctx, augs.child);
7220 }
7221 while (revs.child) {
7222 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007223 }
Radek Krejcie534c132016-11-23 13:32:31 +01007224 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007225 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007226 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007227
PavolVican9e81c6a2017-02-09 13:09:07 +01007228 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007229}
7230
Michal Vasko0d343d12015-08-24 14:57:36 +02007231/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007232struct lys_submodule *
7233yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007234{
Michal Vasko53b7da02018-02-13 15:28:42 +01007235 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007236 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007237 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007238 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007239
Michal Vasko53b7da02018-02-13 15:28:42 +01007240 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007241 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007242 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007243 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007245 /* check root element */
7246 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007247 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007248 goto error;
7249 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007250
Michal Vasko53b7da02018-02-13 15:28:42 +01007251 GETVAL(ctx, value, yin, "name");
7252 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007253 goto error;
7254 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007255
Michal Vasko5a721fd2016-02-16 12:16:48 +01007256 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007257 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007258
Michal Vasko53b7da02018-02-13 15:28:42 +01007259 submodule->ctx = ctx;
7260 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007261 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007262 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007263 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007264
Radek Krejci9e757e02017-03-08 17:18:09 +01007265 /* add into the list of processed modules */
7266 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7267 goto error;
7268 }
7269
Michal Vasko5a721fd2016-02-16 12:16:48 +01007270 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007271 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007272 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007273 goto error;
7274 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007275
Radek Krejci33fc4772017-01-26 16:00:35 +01007276 lyp_sort_revisions((struct lys_module *)submodule);
7277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007278 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007279 lyxml_free(ctx, yin);
7280 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007281
Michal Vasko5a721fd2016-02-16 12:16:48 +01007282 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007283 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007284
7285error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007286 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007287 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007288 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007289 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007290 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007291 }
7292
Michal Vasko53b7da02018-02-13 15:28:42 +01007293 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007294
Michal Vaskoa9728122018-01-16 14:00:13 +01007295 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007296 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007297 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7298 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007299 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007300 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007301}
7302
Michal Vasko0d343d12015-08-24 14:57:36 +02007303/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007304struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007305yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007306{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007307 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007308 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007309 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007310 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007311
Radek Krejcic071c542016-01-27 14:57:51 +01007312 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007313 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007315 /* check root element */
7316 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007317 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007318 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007319 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007320 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007321 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007322 goto error;
7323 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007324
Michal Vasko53b7da02018-02-13 15:28:42 +01007325 GETVAL(ctx, value, yin, "name");
7326 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007327 goto error;
7328 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007330 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007331 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007333 module->ctx = ctx;
7334 module->name = lydict_insert(ctx, value, strlen(value));
7335 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007336 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007337
Radek Krejci9e757e02017-03-08 17:18:09 +01007338 /* add into the list of processed modules */
7339 if (lyp_check_circmod_add(module)) {
7340 goto error;
7341 }
7342
Michal Vasko9f258e42016-02-11 11:36:27 +01007343 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007344 ret = read_sub_module(module, NULL, yin, unres);
7345 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007346 goto error;
7347 }
7348
PavolVican9e81c6a2017-02-09 13:09:07 +01007349 if (ret == 1) {
7350 assert(!unres->count);
7351 } else {
Michal Vasko0f437062018-06-08 15:52:39 +02007352 /* make this module implemented if was not from start */
7353 if (!implement && module->implemented && (unres_schema_add_node(module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1)) {
7354 goto error;
7355 }
7356
PavolVican9e81c6a2017-02-09 13:09:07 +01007357 /* resolve rest of unres items */
7358 if (unres->count && resolve_unres_schema(module, unres)) {
7359 goto error;
7360 }
7361
7362 /* check correctness of includes */
7363 if (lyp_check_include_missing(module)) {
7364 goto error;
7365 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007366 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007367
Radek Krejci95f22ae2017-01-20 14:25:53 +01007368 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007369
7370 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7371 goto error;
7372 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007373
Radek Krejciff4874d2016-03-07 12:30:50 +01007374 if (revision) {
7375 /* check revision of the parsed model */
7376 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007377 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7378 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007379 goto error;
7380 }
7381 }
7382
PavolVican9e81c6a2017-02-09 13:09:07 +01007383 /* add into context if not already there */
7384 if (!ret) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007385 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007386 goto error;
7387 }
Michal Vasko10681e82018-01-16 14:54:16 +01007388
7389 /* remove our submodules from the parsed submodules list */
7390 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007391 } else {
7392 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007393 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007394
7395 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007396 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007397 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007398 }
7399
Michal Vasko44ab1462017-05-18 13:18:36 +02007400 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007401 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007402 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7403 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007404 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007405
7406error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007407 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007408 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007409
7410 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007411 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7412 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007413 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007414 return NULL;
7415 }
7416
Michal Vasko53b7da02018-02-13 15:28:42 +01007417 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007418
Radek Krejci9e757e02017-03-08 17:18:09 +01007419 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007420 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007421 lyp_del_includedup(module, 1);
7422 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007423 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007424}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007425
Radek Krejci37f9ba32017-02-10 16:50:35 +01007426/* logs directly */
7427struct lys_module *
7428yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7429{
7430 struct lyxml_elem *yin;
7431 struct lys_module *result;
7432
Radek Krejcie1bacd72017-03-01 13:18:46 +01007433 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007434 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007435 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007436 return NULL;
7437 }
7438
7439 result = yin_read_module_(ctx, yin, revision, implement);
7440
7441 lyxml_free(ctx, yin);
7442
7443 return result;
7444}
7445
Radek Krejcic1885952017-02-07 09:37:51 +01007446static int
7447yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007448 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007449 const char *true_val, const char *false_val, struct unres_schema *unres)
7450{
7451 uint8_t *val;
7452 const char *str;
7453 struct lyext_substmt *info;
7454
7455 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7456 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007457 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007458 return EXIT_FAILURE;
7459 }
7460 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007461 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007462 return EXIT_FAILURE;
7463 }
7464
Radek Krejcidb35f172017-02-27 11:03:01 +01007465 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007466 return EXIT_FAILURE;
7467 }
7468
7469 str = lyxml_get_attr(node, "value", NULL);
7470 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007471 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007472 } else if (true_val && !strcmp(true_val, str)) {
7473 /* true value */
7474 *val = 1;
7475 } else if (false_val && !strcmp(false_val, str)) {
7476 /* false value */
7477 *val = 2;
7478 } else {
7479 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007480 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007481 return EXIT_FAILURE;
7482 }
7483
7484 return EXIT_SUCCESS;
7485}
7486
Radek Krejci8d6b7422017-02-03 14:42:13 +01007487/*
7488 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7489 * argname - name of the element/attribute where the value is stored
7490 */
7491static int
7492yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007493 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007494 int argelem, const char *argname, struct unres_schema *unres)
7495{
7496 int c;
PavolVican99c70722017-02-18 17:25:52 +01007497 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007498 void *reallocated;
7499 struct lyext_substmt *info;
7500
7501 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7502 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007503 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007504 return EXIT_FAILURE;
7505 }
7506 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007507 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007508 return EXIT_FAILURE;
7509 }
7510
7511 c = 0;
7512 if (info->cardinality >= LY_STMT_CARD_SOME) {
7513 /* there can be multiple instances, str is actually const char *** */
7514 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007515 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007516 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007517 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007518 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007519 if (stmt == LY_STMT_BELONGSTO) {
7520 /* allocate another array for the belongs-to's prefixes */
7521 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007522 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007523 } else if (stmt == LY_STMT_ARGUMENT) {
7524 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007525 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007526 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007527 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007528 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007529 /* get the index in the array to add new item */
7530 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007531 }
Radek Krejci56c80412017-02-09 10:44:16 +01007532 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007533 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007534 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007535 return EXIT_FAILURE;
7536 }
7537
7538 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007539 str[c] = read_yin_subnode(mod->ctx, node, argname);
7540 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007541 return EXIT_FAILURE;
7542 }
Radek Krejci56c80412017-02-09 10:44:16 +01007543 } else {
7544 str[c] = lyxml_get_attr(node, argname, NULL);
7545 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007546 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007547 return EXIT_FAILURE;
7548 } else {
7549 str[c] = lydict_insert(mod->ctx, str[c], 0);
7550 }
7551
7552 if (stmt == LY_STMT_BELONGSTO) {
7553 /* get the belongs-to's mandatory prefix substatement */
7554 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007555 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007556 return EXIT_FAILURE;
7557 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007558 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007559 return EXIT_FAILURE;
7560 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007561 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007562 return EXIT_FAILURE;
7563 }
7564 /* and now finally get the value */
7565 if (p) {
7566 str = p[1];
7567 } else {
7568 str++;
7569 }
7570 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7571 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007572 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007573 return EXIT_FAILURE;
7574 }
7575 str[c] = lydict_insert(mod->ctx, str[c], 0);
7576
PavolVican6d400872017-03-01 15:19:18 +01007577 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 +01007578 return EXIT_FAILURE;
7579 }
PavolVican99c70722017-02-18 17:25:52 +01007580 } else if (stmt == LY_STMT_ARGUMENT) {
7581 str = (p) ? p[1] : str + 1;
7582 if (!node->child) {
7583 /* default value of yin element */
7584 ((uint8_t *)str)[c] = 2;
7585 } else {
7586 /* get optional yin-element substatement */
7587 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007588 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007589 return EXIT_FAILURE;
7590 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007591 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007592 return EXIT_FAILURE;
7593 } else {
7594 /* and now finally get the value */
7595 value = lyxml_get_attr(node->child, "value", NULL);
7596 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007597 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007598 return EXIT_FAILURE;
7599 }
7600 if (ly_strequal(value, "true", 0)) {
7601 ((uint8_t *)str)[c] = 1;
7602 } else if (ly_strequal(value, "false", 0)) {
7603 ((uint8_t *)str)[c] = 2;
7604 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007605 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007606 return EXIT_FAILURE;
7607 }
7608
7609 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7610 return EXIT_FAILURE;
7611 }
7612 }
7613 }
Radek Krejci56c80412017-02-09 10:44:16 +01007614 }
7615 }
7616 if (p) {
7617 /* enlarge the array(s) */
7618 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7619 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007620 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007621 lydict_remove(mod->ctx, p[0][c]);
7622 p[0][c] = NULL;
7623 return EXIT_FAILURE;
7624 }
7625 p[0] = reallocated;
7626 p[0][c + 1] = NULL;
7627
7628 if (stmt == LY_STMT_BELONGSTO) {
7629 /* enlarge the second belongs-to's array with prefixes */
7630 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7631 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007632 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007633 lydict_remove(mod->ctx, p[1][c]);
7634 p[1][c] = NULL;
7635 return EXIT_FAILURE;
7636 }
7637 p[1] = reallocated;
7638 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007639 } else if (stmt == LY_STMT_ARGUMENT){
7640 /* enlarge the second argument's array with yin element */
7641 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7642 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007643 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007644 ((uint8_t *)p[1])[c] = 0;
7645 return EXIT_FAILURE;
7646 }
7647 p[1] = reallocated;
7648 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007649 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007650 }
7651
7652 return EXIT_SUCCESS;
7653}
7654
7655static void *
7656yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7657 uint16_t mask)
7658{
7659 void *data;
7660 struct lyext_substmt *info;
7661
7662 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7663 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007664 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007665 return NULL;
7666 }
7667 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007668 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007669 return NULL;
7670 }
7671
7672 return data;
7673}
7674
Radek Krejcic1885952017-02-07 09:37:51 +01007675static int
7676yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007677 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007678 const char *val1_str, const char *val2_str, uint16_t mask,
7679 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7680{
7681 uint16_t *val;
7682 const char *str;
7683
7684 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7685 if (!val) {
7686 return EXIT_FAILURE;
7687 }
7688
7689 str = lyxml_get_attr(node, "value", NULL);
7690 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007691 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007692 } else if (!strcmp(val1_str, str)) {
7693 *val = *val | val1;
7694 } else if (!strcmp(val2_str, str)) {
7695 *val = *val | val2;
7696 } else {
7697 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007698 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007699 return EXIT_FAILURE;
7700 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007701 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007702 return EXIT_FAILURE;
7703 }
7704 return EXIT_SUCCESS;
7705}
7706
Radek Krejcif95b6292017-02-13 15:57:37 +01007707static struct lys_node **
7708yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7709{
7710 struct lyext_substmt *info;
7711 struct lys_node **snode, *siter;
7712
7713 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7714 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007715 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007716 return NULL;
7717 }
7718 if (info->cardinality < LY_STMT_CARD_SOME) {
7719 LY_TREE_FOR(*snode, siter) {
7720 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007721 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007722 return NULL;
7723 }
7724 }
7725 }
7726
7727 return snode;
7728}
7729
Radek Krejci8d6b7422017-02-03 14:42:13 +01007730static void **
7731yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7732{
7733 int c;
7734 void **data, ***p = NULL;
7735 void *reallocated;
7736 struct lyext_substmt *info;
7737
7738 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7739 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007740 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007741 return NULL;
7742 }
7743 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007744 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007745 return NULL;
7746 }
7747
7748 c = 0;
7749 if (info->cardinality >= LY_STMT_CARD_SOME) {
7750 /* there can be multiple instances, so instead of pointer to array,
7751 * we have in data pointer to pointer to array */
7752 p = (void ***)data;
7753 data = *p;
7754 if (!data) {
7755 /* allocate initial array */
7756 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007757 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007758 } else {
7759 for (c = 0; *data; data++, c++);
7760 }
7761 }
7762
7763 if (p) {
7764 /* enlarge the array */
7765 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007766 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007767 *p = reallocated;
7768 data = *p;
7769 data[c + 1] = NULL;
7770 }
7771
7772 return &data[c];
7773}
7774
7775int
7776lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7777 struct unres_schema *unres)
7778{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007779 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007780 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007781 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007782 const char *value, *name;
7783 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007784 struct lyext_substmt *info;
7785 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007786 long long int ll;
7787 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007788 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007789
Radek Krejcia8d111f2017-05-31 13:57:37 +02007790#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7791 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007792 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007793 (**(TYPE **)TO) = (TYPE)FROM;
7794
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007795#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007796 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7797 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007798 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007799 goto error; \
7800 } \
7801 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007802 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007803 goto error; \
7804 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007805 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007806 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7807 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007808 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007809 if (!(*pp)) { \
7810 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007811 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007812 } else { \
7813 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7814 } \
7815 p = &(*(TYPE**)pp)[i]; \
7816 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007817#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007818 if (pp) { \
7819 /* enlarge the array */ \
7820 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007821 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007822 *pp = reallocated; \
7823 (*(TYPE**)pp)[i + 1] = 0; \
7824 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007825#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7826 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7827 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007828 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007829#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7830 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007831 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007832 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007833 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007834 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7835 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7836 goto error; \
7837 } \
7838 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007839
Radek Krejci8d6b7422017-02-03 14:42:13 +01007840 LY_TREE_FOR_SAFE(yin->child, next, node) {
7841 if (!node->ns) {
7842 /* garbage */
7843 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7844 /* we have the extension's argument */
7845 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007846 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007847 goto error;
7848 }
7849 ext->arg_value = node->content;
7850 node->content = NULL;
7851 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7852 /* extension */
7853 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7854 goto error;
7855 }
7856 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007857 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007858 goto error;
7859 }
7860 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007861 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007862 goto error;
7863 }
7864 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007865 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007866 goto error;
7867 }
7868 } else if (!strcmp(node->name, "type")) {
7869 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7870 if (!type) {
7871 goto error;
7872 }
7873 /* allocate type structure */
7874 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007875 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007876
7877 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007878 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007879 (*type)->der = (struct lys_tpdf *)node;
7880 (*type)->parent = (struct lys_tpdf *)ext;
7881
7882 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7883 (*type)->der = NULL;
7884 goto error;
7885 }
7886 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007887 } else if (!strcmp(node->name, "typedef")) {
7888 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7889 if (!pp) {
7890 goto error;
7891 }
7892 /* allocate typedef structure */
7893 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007894 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007895
7896 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7897 goto error;
7898 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007899 } else if (!strcmp(node->name, "if-feature")) {
7900 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7901 if (!pp) {
7902 goto error;
7903 }
7904 /* allocate iffeature structure */
7905 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007906 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007907
7908 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7909 goto error;
7910 }
7911 } else if (!strcmp(node->name, "status")) {
7912 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7913 if (!p) {
7914 goto error;
7915 }
7916
Michal Vasko53b7da02018-02-13 15:28:42 +01007917 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007918 if (!strcmp(value, "current")) {
7919 *(uint16_t*)p |= LYS_STATUS_CURR;
7920 } else if (!strcmp(value, "deprecated")) {
7921 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7922 } else if (!strcmp(value, "obsolete")) {
7923 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7924 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007925 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007926 goto error;
7927 }
7928
7929 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7930 goto error;
7931 }
Radek Krejcic1885952017-02-07 09:37:51 +01007932 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007933 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007934 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007935 goto error;
7936 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007937 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007938 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007939 goto error;
7940 }
7941 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007942 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007943 goto error;
7944 }
Radek Krejcic1885952017-02-07 09:37:51 +01007945 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007946 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007947 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7948 goto error;
7949 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007950 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007951 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007952 goto error;
7953 }
7954 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007955 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007956 goto error;
7957 }
7958 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007959 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007960 goto error;
7961 }
7962 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007963 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007964 goto error;
7965 }
7966 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007967 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007968 goto error;
7969 }
7970 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007971 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007972 goto error;
7973 }
7974 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007975 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007976 goto error;
7977 }
7978 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007979 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007980 goto error;
7981 }
Radek Krejcic1885952017-02-07 09:37:51 +01007982 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007983 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7984 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007985 goto error;
7986 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007987 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007988 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007989 goto error;
7990 }
7991 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007992 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007993 goto error;
7994 }
7995 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007996 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007997 goto error;
7998 }
7999 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008000 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008001 goto error;
8002 }
Radek Krejcic1885952017-02-07 09:37:51 +01008003 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008004 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008005 goto error;
8006 }
8007 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008008 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008009 goto error;
8010 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008011 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008012 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008013
Michal Vasko53b7da02018-02-13 15:28:42 +01008014 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008015 v = strtol(value, NULL, 10);
8016
8017 /* range check */
8018 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008019 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008020 goto error;
8021 }
8022
8023 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
8024 goto error;
8025 }
8026
8027 /* store the value */
8028 (*(uint8_t *)p) = (uint8_t)v;
8029
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008030 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008031 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008032 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008033
Michal Vasko53b7da02018-02-13 15:28:42 +01008034 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008035 while (isspace(value[0])) {
8036 value++;
8037 }
8038
8039 if (!strcmp(value, "unbounded")) {
8040 u = 0;
8041 } else {
8042 /* convert it to uint32_t */
8043 errno = 0; endptr = NULL;
8044 u = strtoul(value, &endptr, 10);
8045 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008046 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008047 goto error;
8048 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008049 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008050
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 Krejci5496fae2017-02-10 13:26:48 +01008059 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008060 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008061
Michal Vasko53b7da02018-02-13 15:28:42 +01008062 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008063 while (isspace(value[0])) {
8064 value++;
8065 }
8066
8067 /* convert it to uint32_t */
8068 errno = 0;
8069 endptr = NULL;
8070 u = strtoul(value, &endptr, 10);
8071 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008072 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008073 goto error;
8074 }
8075
8076 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8077 goto error;
8078 }
8079
8080 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008081 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008082
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008083 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008084 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008085 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8086
Michal Vasko53b7da02018-02-13 15:28:42 +01008087 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008088 while (isspace(value[0])) {
8089 value++;
8090 }
8091
8092 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008093 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008094
8095 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008096 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008097 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008098 goto error;
8099 }
8100
8101 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8102 goto error;
8103 }
8104
8105 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008106 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008107
8108 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008109 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008110 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008111
Michal Vasko53b7da02018-02-13 15:28:42 +01008112 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008113 ll = strtoll(value, NULL, 10);
8114
8115 /* range check */
8116 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008117 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008118 goto error;
8119 }
8120
8121 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8122 goto error;
8123 }
8124
8125 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008126 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008127
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008128 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008129 } else if (!strcmp(node->name, "module")) {
8130 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8131 if (!pp) {
8132 goto error;
8133 }
8134
8135 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8136 if (!(*pp)) {
8137 goto error;
8138 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008139 } else if (!strcmp(node->name, "when")) {
8140 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8141
8142 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8143 if (!*(struct lys_when**)p) {
8144 goto error;
8145 }
8146
8147 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008148 } else if (!strcmp(node->name, "revision")) {
8149 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8150
8151 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008152 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008153 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8154 goto error;
8155 }
8156
8157 /* check uniqueness of the revision dates - not required by RFC */
8158 if (pp) {
8159 for (j = 0; j < i; j++) {
8160 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008161 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008162 }
8163 }
8164 }
8165
8166 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008167 } else if (!strcmp(node->name, "unique")) {
8168 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8169
8170 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008171 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008172 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8173 goto error;
8174 }
8175
8176 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8177 goto error;
8178 }
8179 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008180 } else if (!strcmp(node->name, "action")) {
8181 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8182 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008183 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008184 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008185 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008186 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008187 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008188 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008189 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008190 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008191 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008192 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008193 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008194 } else if (!strcmp(node->name, "output")) {
8195 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8196 } else if (!strcmp(node->name, "input")) {
8197 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8198 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008199 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008200 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008201 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008202 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008203 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008204 } else if (!strcmp(node->name, "notification")) {
8205 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8206 } else if (!strcmp(node->name, "uses")) {
8207 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008208 } else if (!strcmp(node->name, "length")) {
8209 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8210 } else if (!strcmp(node->name, "must")) {
8211 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8212 if (!pp) {
8213 goto error;
8214 }
8215 /* allocate structure for must */
8216 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008217 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008218
8219 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8220 goto error;
8221 }
8222 } else if (!strcmp(node->name, "pattern")) {
8223 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008224 GETVAL(mod->ctx, value, node, "value");
8225 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008226 goto error;
8227 }
8228
8229 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008230 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008231
8232 modifier = 0x06; /* ACK */
8233 if (mod->version >= 2) {
8234 name = NULL;
8235 LY_TREE_FOR(node->child, child) {
8236 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8237 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008238 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008239 goto error;
8240 }
8241
Michal Vasko53b7da02018-02-13 15:28:42 +01008242 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008243 if (!strcmp(name, "invert-match")) {
8244 modifier = 0x15; /* NACK */
8245 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008246 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008247 goto error;
8248 }
8249 /* get extensions of the modifier */
8250 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8251 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8252 goto error;
8253 }
8254 }
8255 }
8256 }
8257
8258 /* store the value: modifier byte + value + terminating NULL byte */
8259 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008260 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008261 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8262 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8263 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8264
8265 /* get possible sub-statements */
8266 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8267 goto error;
8268 }
8269
8270 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8271 } else if (!strcmp(node->name, "range")) {
8272 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008273 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008274 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008275 }
8276 lyxml_free(mod->ctx, node);
8277 }
8278
PavolVicanc4b798e2017-02-20 23:15:27 +01008279 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8280 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008281 }
8282
Radek Krejci8d6b7422017-02-03 14:42:13 +01008283 return EXIT_SUCCESS;
8284
8285error:
8286 return EXIT_FAILURE;
8287}