blob: 3fc3a6f8102518c1c91ab5837c3369ef677da481 [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 */
Michal Vaskoa2049012019-07-18 13:26:29 +02001298 if (!parenttype && lys_ingrouping(parent)) {
1299 /* just a flag - do not resolve */
1300 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001301 }
1302
Radek Krejcidc4c1412015-06-19 15:39:54 +02001303 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001304 LY_TREE_FOR(yin->child, node) {
Michal Vasko7560ac42019-07-01 08:54:59 +02001305 if (!strcmp(node->name, "path") && !type->der->type.der) {
1306 /* keep path for later */
1307 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
1308 if (type->info.lref.req) {
1309 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1310 goto error;
1311 }
1312 GETVAL(ctx, value, node, "value");
1313 if (!strcmp(value, "true")) {
1314 type->info.lref.req = 1;
1315 } else if (!strcmp(value, "false")) {
1316 type->info.lref.req = -1;
1317 } else {
1318 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1319 goto error;
1320 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001321
Michal Vasko7560ac42019-07-01 08:54:59 +02001322 /* extensions */
1323 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
1324 goto error;
1325 }
1326 } else {
1327 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1328 goto error;
1329 }
1330 }
1331
1332 /* now that require-instance is properly set, try to find and resolve path */
1333 LY_TREE_FOR(yin->child, node) {
Michal Vasko88c29542015-11-27 14:57:53 +01001334 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001335 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001336 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001337 goto error;
1338 }
1339
Michal Vasko53b7da02018-02-13 15:28:42 +01001340 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001341 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001342 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001343 if (!type->info.lref.path) {
1344 goto error;
1345 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001346
1347 /* try to resolve leafref path only when this is instantiated
1348 * leaf, so it is not:
1349 * - typedef's type,
1350 * - in grouping definition,
1351 * - just instantiated in a grouping definition,
1352 * because in those cases the nodes referenced in path might not be present
1353 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001354 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001355 goto error;
1356 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001357
1358 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001359 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001360 goto error;
1361 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001362
Michal Vasko7560ac42019-07-01 08:54:59 +02001363 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001364 }
Radek Krejci73adb602015-07-02 18:07:40 +02001365 }
1366
Radek Krejci742be352016-07-17 12:18:54 +02001367 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001368 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001369 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001370 goto error;
1371 } else {
1372 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001373 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001374 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001375 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001376 goto error;
1377 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001378 }
Radek Krejci742be352016-07-17 12:18:54 +02001379 }
1380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001381 break;
1382
1383 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001384 /* RFC 6020 9.4.4 - length */
1385 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001386 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001387 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001388
Radek Krejci3733a802015-06-19 13:43:21 +02001389 if (!strcmp(node->name, "length")) {
1390 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001391 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001392 goto error;
1393 }
1394
Michal Vasko53b7da02018-02-13 15:28:42 +01001395 GETVAL(ctx, value, node, "value");
1396 if (lyp_check_length_range(ctx, value, type)) {
1397 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001398 goto error;
1399 }
1400 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001401 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1402 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001403
Radek Krejci5fbc9162015-06-19 14:11:11 +02001404 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001405 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001406 goto error;
1407 }
PavolVican92f23622017-12-12 13:35:56 +01001408
1409 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1410 /* set flag, which represent LYEXT_OPT_VALID */
1411 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001412 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001413 break;
1414 }
1415 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001416 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001417 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001418 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001419 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001420 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001421 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001422 goto error;
1423 }
1424 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001425 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001426 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001427 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001428 in_grp = 1;
1429 }
Radek Krejci73adb602015-07-02 18:07:40 +02001430 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001431 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001432#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001433 if (!in_grp) {
1434 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001435 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001436 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001437 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001438#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001439 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001440 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001441
Michal Vasko9c7dee32018-07-09 09:12:59 +02001442 if (in_grp) {
1443 /* in grouping, just check the pattern syntax */
1444 if (!(ctx->models.flags & LY_CTX_TRUSTED) && lyp_check_pattern(ctx, value, NULL)) {
1445 goto error;
Radek Krejcib53154b2017-07-19 09:14:13 +02001446 }
Michal Vasko69068852015-07-13 14:34:31 +02001447 }
Michal Vasko9c7dee32018-07-09 09:12:59 +02001448#ifdef LY_ENABLED_CACHE
1449 else {
1450 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
1451 if (lyp_precompile_pattern(ctx, value,
1452 (pcre **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1453 (pcre_extra **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1454 goto error;
1455 }
1456 }
1457#endif
Radek Krejcifccd1442017-01-16 10:26:57 +01001458 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001459 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001460
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001461 modifier = 0x06; /* ACK */
1462 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001463 if (module->version >= 2) {
1464 LY_TREE_FOR_SAFE(node->child, next2, child) {
1465 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1466 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001467 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001468 goto error;
1469 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001470
Michal Vasko53b7da02018-02-13 15:28:42 +01001471 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001472 if (!strcmp(name, "invert-match")) {
1473 modifier = 0x15; /* NACK */
1474 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001475 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001476 goto error;
1477 }
1478 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001479 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001480 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1481 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001482 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001483
Michal Vasko53b7da02018-02-13 15:28:42 +01001484 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001485 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001486 }
1487 }
1488
1489 len = strlen(value);
1490 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001491 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001492 buf[0] = modifier;
1493 strcpy(&buf[1], value);
1494
Michal Vasko53b7da02018-02-13 15:28:42 +01001495 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001496
1497 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001498 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001499 goto error;
1500 }
PavolVican92f23622017-12-12 13:35:56 +01001501
1502 for (j = 0; j < restr->ext_size; ++j) {
1503 /* set flag, which represent LYEXT_OPT_VALID */
1504 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001505 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001506 break;
1507 }
1508 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001509 }
1510 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001511 break;
1512
1513 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001514 /* RFC 6020 7.4 - type */
1515 /* count number of types in union */
1516 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001517 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001518
Radek Krejcie4c366b2015-07-02 10:11:31 +02001519 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001520 if (type->der->type.der) {
1521 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001522 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001523 goto error;
1524 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001525 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001526 i++;
1527 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001528 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001529 goto error;
1530 }
1531 }
1532
Radek Krejci038d5d92016-09-12 15:07:15 +02001533 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001534 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001535 goto error;
1536 }
1537
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001538 /* inherit instid presence information */
1539 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1540 type->info.uni.has_ptr_type = 1;
1541 }
1542
Radek Krejcie4c366b2015-07-02 10:11:31 +02001543 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001544 if (i) {
1545 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001546 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001547 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001548
Radek Krejcie4c366b2015-07-02 10:11:31 +02001549 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001550 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001551 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001552 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001553 if (!rc) {
1554 type->info.uni.count++;
1555
Radek Krejci7de36cf2016-09-12 16:18:50 +02001556 if (module->version < 2) {
1557 /* union's type cannot be empty or leafref */
1558 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001559 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001560 rc = -1;
1561 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001562 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001563 rc = -1;
1564 }
Michal Vasko88c29542015-11-27 14:57:53 +01001565 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001566
1567 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001568 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1569 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1570 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001571 type->info.uni.has_ptr_type = 1;
1572 }
Michal Vasko88c29542015-11-27 14:57:53 +01001573 }
1574 if (rc) {
1575 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1576 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001577 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001578 }
1579 free(type->info.uni.types);
1580 type->info.uni.types = NULL;
1581 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001582 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001583 type->der = NULL;
1584 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001585
1586 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001587 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001588 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001589 goto error;
1590 }
Michal Vasko88c29542015-11-27 14:57:53 +01001591 }
1592 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001593
Michal Vasko88c29542015-11-27 14:57:53 +01001594 case LY_TYPE_BOOL:
1595 case LY_TYPE_EMPTY:
1596 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001597 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001598 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001599 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 break;
1602
1603 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001604 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001605 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 }
1607
PavolVican92f23622017-12-12 13:35:56 +01001608 for(j = 0; j < type->ext_size; ++j) {
1609 /* set flag, which represent LYEXT_OPT_VALID */
1610 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001611 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001612 break;
1613 }
1614 }
1615
1616 /* if derived type has extension, which need validate data */
1617 dertype = &type->der->type;
1618 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001619 if (dertype->parent->flags & LYS_VALID_EXT) {
1620 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001621 }
1622 dertype = &dertype->der->type;
1623 }
1624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001626
1627error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001628 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001629 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001630}
1631
Michal Vasko0d343d12015-08-24 14:57:36 +02001632/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001633static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001634fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1635 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001636{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001637 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001638 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001639 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001640 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001641 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001642
Michal Vasko53b7da02018-02-13 15:28:42 +01001643 GETVAL(ctx, value, yin, "name");
1644 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001645 goto error;
1646 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001647 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001650 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001651 goto error;
1652 }
Radek Krejcieac35532015-05-31 19:09:15 +02001653
Michal Vasko88c29542015-11-27 14:57:53 +01001654 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001655 if (strcmp(node->ns->value, LY_NSYIN)) {
1656 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001657 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001658 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001659 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001660 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001661 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001662 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 goto error;
1664 }
Michal Vasko88c29542015-11-27 14:57:53 +01001665 /* HACK for unres */
1666 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001667 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001668 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001669 goto error;
1670 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001671 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001672
Radek Krejci07d0fb92017-01-13 14:11:05 +01001673 /* 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 +01001674 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001675 } else if (!strcmp(node->name, "default")) {
1676 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001677 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 goto error;
1679 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001680 GETVAL(ctx, value, node, "value");
1681 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001682
Radek Krejci8d6b7422017-02-03 14:42:13 +01001683 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001684 goto error;
1685 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001686 } else if (!strcmp(node->name, "units")) {
1687 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001688 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 goto error;
1690 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001691 GETVAL(ctx, value, node, "name");
1692 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001693
Radek Krejci8d6b7422017-02-03 14:42:13 +01001694 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001695 goto error;
1696 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001697 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001698 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001699 goto error;
1700 }
Radek Krejcie534c132016-11-23 13:32:31 +01001701
Michal Vasko53b7da02018-02-13 15:28:42 +01001702 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001706 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001707 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 goto error;
1709 }
Radek Krejcieac35532015-05-31 19:09:15 +02001710
Michal Vasko478c4652016-07-21 12:55:01 +02001711 /* check default value (if not defined, there still could be some restrictions
1712 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001713 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001714 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001715 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001716 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001717
Radek Krejcie534c132016-11-23 13:32:31 +01001718 /* finish extensions parsing */
1719 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001720 /* some extensions may be already present from the substatements */
1721 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001722 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001723 tpdf->ext = reallocated;
1724
1725 /* init memory */
1726 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1727
Radek Krejcie534c132016-11-23 13:32:31 +01001728 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001729 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 +01001730 tpdf->ext_size++;
1731 if (rc) {
1732 goto error;
1733 }
1734 }
1735 }
1736
PavolVican92f23622017-12-12 13:35:56 +01001737 for (i = 0; i < tpdf->ext_size; ++i) {
1738 /* set flag, which represent LYEXT_OPT_VALID */
1739 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001740 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001741 break;
1742 }
1743 }
1744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001746
1747error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001748 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001749}
1750
Radek Krejcia1a6b762016-11-14 09:53:38 +09001751static int
Radek Krejcie534c132016-11-23 13:32:31 +01001752fill_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 +09001753{
Michal Vasko53b7da02018-02-13 15:28:42 +01001754 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001755 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001756 struct lyxml_elem *child, *node, *next, *next2;
1757 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001758 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001759
Michal Vasko53b7da02018-02-13 15:28:42 +01001760 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001761
Michal Vasko53b7da02018-02-13 15:28:42 +01001762 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001763 goto error;
1764 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001765 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001766
Radek Krejci07d0fb92017-01-13 14:11:05 +01001767 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001768 goto error;
1769 }
1770
Radek Krejcie534c132016-11-23 13:32:31 +01001771 LY_TREE_FOR_SAFE(yin->child, next, node) {
1772 if (strcmp(node->ns->value, LY_NSYIN)) {
1773 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001774 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001775 c_ext++;
1776 } else if (!strcmp(node->name, "argument")) {
1777 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001778 GETVAL(ctx, value, node, "name");
1779 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001780 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001781 goto error;
1782 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001783
Radek Krejcia1a6b762016-11-14 09:53:38 +09001784 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001785 LY_TREE_FOR_SAFE(node->child, next2, child) {
1786 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001787 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001788 if (ly_strequal(value, "true", 0)) {
1789 ext->flags |= LYS_YINELEM;
1790 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001791
Radek Krejci8d6b7422017-02-03 14:42:13 +01001792 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001793 goto error;
1794 }
Radek Krejcie534c132016-11-23 13:32:31 +01001795 } else if (child->ns) {
1796 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001797 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001798 goto error;
1799 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001800 }
1801
Michal Vasko53b7da02018-02-13 15:28:42 +01001802 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001803 } else {
1804 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001805 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001806 goto error;
1807 }
1808 }
1809
1810 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001811 /* some extensions may be already present from the substatements */
1812 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001813 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001814 ext->ext = reallocated;
1815
1816 /* init memory */
1817 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1818
1819 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001820 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001821 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 +01001822 ext->ext_size++;
1823 if (rc) {
1824 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001825 }
1826 }
1827 }
1828
Radek Krejci0a498f82017-01-04 16:24:15 +01001829 /* search for plugin */
1830 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 +09001831
1832 return EXIT_SUCCESS;
1833
1834error:
1835 return EXIT_FAILURE;
1836}
1837
Michal Vasko0d343d12015-08-24 14:57:36 +02001838/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001839static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001840fill_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 +02001841{
Michal Vasko53b7da02018-02-13 15:28:42 +01001842 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001843 const char *value;
1844 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001845 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001846 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001847
Michal Vasko53b7da02018-02-13 15:28:42 +01001848 GETVAL(ctx, value, yin, "name");
1849 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001850 goto error;
1851 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001852 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001853 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001854
Radek Krejci07d0fb92017-01-13 14:11:05 +01001855 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001856 goto error;
1857 }
1858
Radek Krejcie534c132016-11-23 13:32:31 +01001859 LY_TREE_FOR(yin->child, child) {
1860 if (strcmp(child->ns->value, LY_NSYIN)) {
1861 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001862 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001863 c_ext++;
1864 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001865 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001866 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001867 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001868 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001869 goto error;
1870 }
1871 }
1872
Radek Krejcie534c132016-11-23 13:32:31 +01001873 if (c_ftrs) {
1874 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001875 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001876 }
Radek Krejcie534c132016-11-23 13:32:31 +01001877 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001878 /* some extensions may be already present from the substatements */
1879 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001880 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001881 f->ext = reallocated;
1882
1883 /* init memory */
1884 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001885 }
1886
Radek Krejcie534c132016-11-23 13:32:31 +01001887 LY_TREE_FOR_SAFE(yin->child, next, child) {
1888 if (strcmp(child->ns->value, LY_NSYIN)) {
1889 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001890 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 +01001891 f->ext_size++;
1892 if (ret) {
1893 goto error;
1894 }
1895 } else { /* if-feature */
1896 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1897 f->iffeature_size++;
1898 if (ret) {
1899 goto error;
1900 }
1901 }
1902 }
1903
Radek Krejcic79c6b12016-07-26 15:11:49 +02001904 /* check for circular dependencies */
1905 if (f->iffeature_size) {
1906 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1907 goto error;
1908 }
1909 }
1910
Radek Krejci3cf9e222015-06-18 11:37:50 +02001911 return EXIT_SUCCESS;
1912
1913error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001914 return EXIT_FAILURE;
1915}
1916
Michal Vasko0d343d12015-08-24 14:57:36 +02001917/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001919fill_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 +02001920{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001922
Michal Vasko53b7da02018-02-13 15:28:42 +01001923 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001924 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001925 if (!must->expr) {
1926 goto error;
1927 }
Radek Krejci800af702015-06-02 13:46:01 +02001928
Radek Krejciaa9c5202017-02-15 16:10:14 +01001929 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001930
Michal Vasko77dc5652016-02-15 12:32:42 +01001931error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001932 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001933}
1934
Radek Krejci581ce772015-11-10 17:22:40 +01001935static int
Radek Krejci7417a082017-02-16 11:07:59 +01001936fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1937 struct unres_schema *unres)
1938{
Michal Vasko53b7da02018-02-13 15:28:42 +01001939 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001940 struct lyxml_elem *next, *child;
1941 const char *value;
1942
Michal Vasko53b7da02018-02-13 15:28:42 +01001943 GETVAL(ctx, value, yin, "date");
1944 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001945 goto error;
1946 }
1947 memcpy(rev->date, value, LY_REV_SIZE - 1);
1948
1949 LY_TREE_FOR_SAFE(yin->child, next, child) {
1950 if (!child->ns) {
1951 /* garbage */
1952 continue;
1953 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1954 /* possible extension instance */
1955 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1956 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1957 goto error;
1958 }
1959 } else if (!strcmp(child->name, "description")) {
1960 if (rev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001961 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001962 goto error;
1963 }
1964 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1965 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1966 goto error;
1967 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001968 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001969 if (!rev->dsc) {
1970 goto error;
1971 }
1972 } else if (!strcmp(child->name, "reference")) {
1973 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001974 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001975 goto error;
1976 }
1977 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1978 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1979 goto error;
1980 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001981 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001982 if (!rev->ref) {
1983 goto error;
1984 }
1985 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001986 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001987 goto error;
1988 }
1989 }
1990
1991 return EXIT_SUCCESS;
1992
1993error:
1994 return EXIT_FAILURE;
1995}
1996
1997static int
Michal Vasko88c29542015-11-27 14:57:53 +01001998fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1999 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01002000{
Michal Vasko53b7da02018-02-13 15:28:42 +01002001 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02002002 int i, j, ret = EXIT_FAILURE;
2003 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02002004 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002005 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01002006
2007 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01002008 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01002009
2010 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002011 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01002012 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002013 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002014 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02002015 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01002016 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01002017 while (isspace(*vaux)) {
2018 vaux++;
2019 }
2020 }
2021 unique->expr_size++;
2022 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002023 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002024
2025 for (i = 0; i < unique->expr_size; i++) {
2026 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02002027 if (vaux) {
2028 c = *vaux;
2029 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01002030 }
2031
2032 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002033 unique->expr[i] = transform_schema2json(module, value);
2034 if (vaux) {
2035 *vaux = c;
2036 }
Radek Krejci581ce772015-11-10 17:22:40 +01002037
2038 /* check that the expression does not repeat */
2039 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002040 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002041 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
2042 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01002043 goto error;
2044 }
2045 }
2046
2047 /* try to resolve leaf */
2048 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002049 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01002050 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02002051 unique_info->list = parent;
2052 unique_info->expr = unique->expr[i];
2053 unique_info->trg_type = &unique->trg_type;
2054 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02002055 goto error;
2056 }
Radek Krejci581ce772015-11-10 17:22:40 +01002057 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002058 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002059 goto error;
2060 }
2061 }
2062
2063 /* move to next token */
2064 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002065 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002066 value++;
2067 }
2068 }
2069
Radek Krejci1a9c3612017-04-24 14:49:43 +02002070 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002071
2072error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002073 free(start);
2074 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002075}
2076
Michal Vasko0d343d12015-08-24 14:57:36 +02002077/* logs directly
2078 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002079 * type: 0 - min, 1 - max
2080 */
2081static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002082deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002083{
2084 const char *value;
2085 char *endptr;
2086 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002087 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002088 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002089
Michal Vaskof7e57d52016-03-07 11:31:09 +01002090 /* del min/max is forbidden */
2091 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002092 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002093 goto error;
2094 }
2095
Radek Krejcieb00f512015-07-01 16:44:58 +02002096 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002097 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002098 max = &((struct lys_node_leaflist *)target)->max;
2099 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002100 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002101 max = &((struct lys_node_list *)target)->max;
2102 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002103 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002104 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2105 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002106 goto error;
2107 }
2108
Michal Vasko53b7da02018-02-13 15:28:42 +01002109 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002110 while (isspace(value[0])) {
2111 value++;
2112 }
2113
Radek Krejci0d7b2472016-02-12 11:11:03 +01002114 if (type && !strcmp(value, "unbounded")) {
2115 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002116 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002117 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002118 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002119 /* convert it to uint32_t */
2120 errno = 0;
2121 endptr = NULL;
2122 val = strtoul(value, &endptr, 10);
2123 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002124 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002125 goto error;
2126 }
2127 if (type) {
2128 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002129 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002130 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002131 } else {
2132 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002133 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002134 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002135 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002136 }
2137
2138 if (d->mod == LY_DEVIATE_ADD) {
2139 /* check that there is no current value */
2140 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002141 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2142 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002143 goto error;
2144 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002145 } else if (d->mod == LY_DEVIATE_RPL) {
2146 /* unfortunately, there is no way to check reliably that there
2147 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002148 }
2149
Michal Vaskof7e57d52016-03-07 11:31:09 +01002150 /* add (already checked) and replace */
2151 /* set new value specified in deviation */
2152 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002153
Pavol Vican09adcc32016-08-25 10:51:36 +02002154 /* check min-elements is smaller than max-elements */
2155 if (*max && *min > *max) {
2156 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002157 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2158 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002159 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002160 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2161 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002162 }
2163 goto error;
2164 }
2165
Radek Krejcieb00f512015-07-01 16:44:58 +02002166 return EXIT_SUCCESS;
2167
2168error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002169 return EXIT_FAILURE;
2170}
2171
Michal Vasko0d343d12015-08-24 14:57:36 +02002172/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002173static int
Michal Vasko88c29542015-11-27 14:57:53 +01002174fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2175 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002176{
2177 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002178 struct lyxml_elem *next, *next2, *child, *develem;
2179 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002180 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002181 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002182 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002183 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002184 struct lys_deviate *d = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002185 struct lys_node *node, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002186 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002187 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002188 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002189 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002190 struct lys_node_leaflist *llist = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002191 struct lys_node_inout *inout;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002192 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002193 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002194 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002195 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002196 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002197 void *reallocated;
Andrew Langefeldf9763242018-09-16 22:23:50 -05002198 size_t deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002199
Michal Vasko53b7da02018-02-13 15:28:42 +01002200 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002201 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002202 if (!dev->target_name) {
2203 goto error;
2204 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002205
2206 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002207 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2208 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002209 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002210 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002211 goto error;
2212 }
Michal Vasko50576712017-07-28 12:28:33 +02002213 dev_target = set->set.s[0];
2214 ly_set_free(set);
2215
Radek Krejcic4283442016-04-22 09:19:27 +02002216 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002217 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2218 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002219 goto error;
2220 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002221
2222 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002223 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002224 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002225 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002226 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002227 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2228 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002229 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002230 c_ext++;
2231 continue;
2232 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002233 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002234 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 goto error;
2236 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002237 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002238 goto error;
2239 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002240 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002241 if (!dev->dsc) {
2242 goto error;
2243 }
2244 } else if (!strcmp(child->name, "reference")) {
2245 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002246 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002247 goto error;
2248 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002249 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002250 goto error;
2251 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002252 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002253 if (!dev->ref) {
2254 goto error;
2255 }
2256 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002257 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002258 c_dev++;
2259
Michal Vasko345da0a2015-12-02 10:35:55 +01002260 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002261 * further processed later
2262 */
2263 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002264
Radek Krejcieb00f512015-07-01 16:44:58 +02002265 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002266 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002267 goto error;
2268 }
2269
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002270 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002271 }
2272
2273 if (c_dev) {
2274 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002275 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002276 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002277 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002278 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002279 }
Radek Krejcie534c132016-11-23 13:32:31 +01002280 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002281 /* some extensions may be already present from the substatements */
2282 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002283 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002284 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002285
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002286 /* init memory */
2287 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2288 }
Radek Krejcie534c132016-11-23 13:32:31 +01002289
2290 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2291 if (strcmp(develem->ns->value, LY_NSYIN)) {
2292 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002293 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 +01002294 dev->ext_size++;
2295 if (rc) {
2296 goto error;
2297 }
2298 continue;
2299 }
2300
2301 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002302 /* init */
2303 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002304 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002305 c_must = 0;
2306 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002307 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002308 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002309
2310 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002311 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002312 if (!strcmp(value, "not-supported")) {
2313 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002314 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002315 * not-supported deviation must be the only deviation of the target
2316 */
2317 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002318 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2319 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 +02002320 goto error;
2321 }
2322
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002323 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002324 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2325 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2326 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002327 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2328 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002329 goto error;
2330 }
2331 }
2332 }
Radek Krejci5b917642015-07-02 09:03:13 +02002333
Michal Vaskoff006c12016-02-17 11:15:19 +01002334 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002335 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002336 lys_node_unlink(dev_target);
Michal Vasko5df038e2018-08-02 09:41:26 +02002337 if (parent) {
2338 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
2339 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2340 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2341 * path), so we need to remember the augment as an addition */
2342 /* remember uses parent so we can reconnect to it */
2343 dev_target->parent = parent;
2344 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
2345 /* re-create implicit node */
2346 inout = calloc(1, sizeof *inout);
2347 LY_CHECK_ERR_GOTO(!inout, LOGMEM(ctx), error);
2348
2349 inout->nodetype = dev_target->nodetype;
2350 inout->name = lydict_insert(ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
2351 inout->module = dev_target->module;
2352 inout->flags = LYS_IMPLICIT;
2353
2354 /* insert it manually */
2355 assert(parent->child && !parent->child->next
2356 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
2357 parent->child->next = (struct lys_node *)inout;
2358 inout->prev = parent->child;
2359 parent->child->prev = (struct lys_node *)inout;
2360 inout->parent = parent;
2361 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01002362 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002363 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002364
Radek Krejcieb00f512015-07-01 16:44:58 +02002365 } else if (!strcmp(value, "add")) {
2366 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2367 } else if (!strcmp(value, "replace")) {
2368 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2369 } else if (!strcmp(value, "delete")) {
2370 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2371 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002372 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002373 goto error;
2374 }
2375 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002376 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002377
Michal Vaskoff006c12016-02-17 11:15:19 +01002378 /* store a shallow copy of the original node */
2379 if (!dev->orig_node) {
2380 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002381 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002382 /* just to be safe */
2383 if (tmp_unres.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002384 LOGINT(ctx);
Michal Vaskoff006c12016-02-17 11:15:19 +01002385 goto error;
2386 }
2387 }
2388
Radek Krejcieb00f512015-07-01 16:44:58 +02002389 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002390 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002391 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002392 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002393 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002394 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002395 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2396 /* extensions */
Michal Vasko53b7da02018-02-13 15:28:42 +01002397 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, d->ext_size, "extensions", "deviate", error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002398 c_ext++;
2399 } else if (d->mod == LY_DEVIATE_NO) {
2400 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002401 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002402 goto error;
2403 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002404 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002405 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002406 goto error;
2407 }
2408
2409 /* for we deviate from RFC 6020 and allow config property even it is/is not
2410 * specified in the target explicitly since config property inherits. So we expect
2411 * that config is specified in every node. But for delete, we check that the value
2412 * is the same as here in deviation
2413 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002414 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002415 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002416 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002417 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002418 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002419 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002420 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002421 goto error;
2422 }
2423
2424 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002425 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002426 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002427 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002428 } else { /* add and replace are the same in this case */
2429 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002430 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002431
2432 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002433 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002434 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002435
Radek Krejci8d6b7422017-02-03 14:42:13 +01002436 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002437 goto error;
2438 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002439 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002440 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 +01002441 goto error;
2442 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002443 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002444 c_dflt++;
2445
2446 /* check target node type */
2447 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002448 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2449 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002450 goto error;
2451 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002452 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2453 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002454 goto error;
2455 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002456 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2457 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002458 goto error;
2459 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002460
Radek Krejcid5a5c282016-08-15 15:38:08 +02002461 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2462 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002463
Radek Krejcieb00f512015-07-01 16:44:58 +02002464 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002465 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002466 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002467 goto error;
2468 }
2469
2470 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002471 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002472 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2473 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002474 goto error;
2475 }
2476
Michal Vasko53b7da02018-02-13 15:28:42 +01002477 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002478 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002479 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002480 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002481 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002482 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002483 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002484 goto error;
2485 }
2486
2487 if (d->mod == LY_DEVIATE_ADD) {
2488 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002489 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002490 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2491 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002492 goto error;
2493 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002494
Radek Krejci841ec082016-04-05 13:05:17 +02002495 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002496 if (d->flags & LYS_MAND_TRUE) {
2497 if (dev_target->nodetype == LYS_CHOICE) {
2498 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002499 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2500 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002501 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2502 goto error;
2503 }
2504 } else if (dev_target->nodetype == LYS_LEAF) {
2505 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002506 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2507 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002508 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2509 goto error;
2510 }
2511 }
Radek Krejci841ec082016-04-05 13:05:17 +02002512 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002513
Michal Vasko21be1b32016-03-07 12:31:34 +01002514 dev_target->flags |= d->flags & LYS_MAND_MASK;
2515 } else if (d->mod == LY_DEVIATE_RPL) {
2516 /* check that there was a value before */
2517 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002518 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2519 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002520 goto error;
2521 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002522
Michal Vasko21be1b32016-03-07 12:31:34 +01002523 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002524 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002525 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002526 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002527 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002528 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002529 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002530
2531 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2532 for (parent = dev_target->parent;
2533 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2534 parent = parent->parent) {
2535 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2536 /* stop also on presence containers */
2537 break;
2538 }
2539 }
2540 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2541 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2542 if (lyp_check_mandatory_choice(parent)) {
2543 goto error;
2544 }
2545 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002546
Radek Krejci8d6b7422017-02-03 14:42:13 +01002547 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002548 goto error;
2549 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002550 } else if (!strcmp(child->name, "min-elements")) {
2551 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002552 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002553 goto error;
2554 }
2555 f_min = 1;
2556
Michal Vasko60f4b452016-02-12 11:02:55 +01002557 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002558 goto error;
2559 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002560 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002561 goto error;
2562 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002563 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002564 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002565 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002566 goto error;
2567 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002568 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002569
Michal Vasko60f4b452016-02-12 11:02:55 +01002570 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002571 goto error;
2572 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002573 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002574 goto error;
2575 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002576 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002577 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002578 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002579 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002580 continue;
2581 } else if (!strcmp(child->name, "type")) {
2582 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002583 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 goto error;
2585 }
2586
Michal Vaskof7e57d52016-03-07 11:31:09 +01002587 /* add, del type is forbidden */
2588 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002589 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002590 goto error;
2591 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002592 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002593 goto error;
2594 }
2595
Radek Krejcieb00f512015-07-01 16:44:58 +02002596 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002597 if (dev_target->nodetype == LYS_LEAF) {
2598 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002599 if (((struct lys_node_leaf *)dev_target)->dflt) {
2600 ly_set_add(dflt_check, dev_target, 0);
2601 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002602 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2603 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002604 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2605 ly_set_add(dflt_check, dev_target, 0);
2606 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002607 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002608 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2609 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002610 goto error;
2611 }
2612
Radek Krejcieb00f512015-07-01 16:44:58 +02002613 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002614 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002615 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002616 /* HACK for unres */
2617 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002618 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002619 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002620 goto error;
2621 }
2622 d->type = t;
2623 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002624 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 +01002625 goto error;
2626 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002627 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002628 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002629 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002630 continue;
2631 } else if (!strcmp(child->name, "units")) {
2632 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002633 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002634 goto error;
2635 }
2636
2637 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002638 if (dev_target->nodetype == LYS_LEAFLIST) {
2639 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2640 } else if (dev_target->nodetype == LYS_LEAF) {
2641 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002642 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002643 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2644 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002645 goto error;
2646 }
2647
2648 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002649 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002650 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002651
2652 /* apply to target */
2653 if (d->mod == LY_DEVIATE_ADD) {
2654 /* check that there is no current value */
2655 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002656 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2657 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002658 goto error;
2659 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002660
Michal Vasko21be1b32016-03-07 12:31:34 +01002661 *stritem = lydict_insert(ctx, value, 0);
2662 } else if (d->mod == LY_DEVIATE_RPL) {
2663 /* check that there was a value before */
2664 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002665 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2666 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002667 goto error;
2668 }
2669
2670 lydict_remove(ctx, *stritem);
2671 *stritem = lydict_insert(ctx, value, 0);
2672 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002673 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002674 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002675 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2676 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002677 goto error;
2678 }
2679 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002680 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002681 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002682
2683 /* remove its extensions */
2684 j = -1;
2685 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2686 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2687 --j;
2688 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002689 }
2690
Radek Krejci8d6b7422017-02-03 14:42:13 +01002691 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002692 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002693 }
2694 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002695 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002696 goto error;
2697 }
2698
Michal Vasko88c29542015-11-27 14:57:53 +01002699 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002700 }
2701
2702 if (c_must) {
2703 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002704 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002705 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002706 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2707 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002708 break;
Radek Krejci76512572015-08-04 09:47:08 +02002709 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002710 trg_must = &((struct lys_node_container *)dev_target)->must;
2711 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002712 break;
Radek Krejci76512572015-08-04 09:47:08 +02002713 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002714 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2715 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002716 break;
Radek Krejci76512572015-08-04 09:47:08 +02002717 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002718 trg_must = &((struct lys_node_list *)dev_target)->must;
2719 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002720 break;
Radek Krejci76512572015-08-04 09:47:08 +02002721 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002722 case LYS_ANYDATA:
2723 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2724 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002725 break;
2726 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002727 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2728 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002729 goto error;
2730 }
2731
Michal Vaskoc04173b2018-03-09 10:43:22 +01002732 dev_target->flags &= ~(LYS_XPCONF_DEP | LYS_XPSTATE_DEP);
Michal Vasko508a50d2016-09-07 14:50:33 +02002733
Radek Krejcieb00f512015-07-01 16:44:58 +02002734 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002735 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002736 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002737 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002738 } else if (d->mod == LY_DEVIATE_ADD) {
2739 /* reallocate the must array of the target */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002740 struct lys_restr *must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
2741 LY_CHECK_ERR_GOTO(!must, LOGMEM(ctx), error);
2742 *trg_must = must;
2743 d->must = calloc(c_must, sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02002744 d->must_size = c_must;
2745 } else { /* LY_DEVIATE_DEL */
2746 d->must = calloc(c_must, sizeof *d->must);
2747 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002748 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002749 }
2750 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002751 /* replace unique is forbidden */
2752 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002753 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002754 goto error;
2755 }
2756
Radek Krejcieb00f512015-07-01 16:44:58 +02002757 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002758 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002759 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2760 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002761 goto error;
2762 }
2763
Michal Vasko60f4b452016-02-12 11:02:55 +01002764 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002765 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002766 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002767 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002768 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002769 list->unique = d->unique;
2770 d->unique = &list->unique[list->unique_size];
2771 d->unique_size = c_uniq;
2772 } else { /* LY_DEVIATE_DEL */
2773 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002774 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002775 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002776 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002777 if (c_dflt) {
2778 if (d->mod == LY_DEVIATE_ADD) {
2779 /* check that there is no current value */
2780 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2781 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002782 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2783 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002784 goto error;
2785 }
2786
2787 /* check collision with mandatory/min-elements */
2788 if ((dev_target->flags & LYS_MAND_TRUE) ||
2789 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002790 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2791 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002792 "Adding the \"default\" statement is forbidden on %s statement.",
2793 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2794 goto error;
2795 }
2796 } else if (d->mod == LY_DEVIATE_RPL) {
2797 /* check that there was a value before */
2798 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2799 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002800 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2801 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002802 goto error;
2803 }
2804 }
2805
2806 if (dev_target->nodetype == LYS_LEAFLIST) {
2807 /* reallocate default list in the target */
2808 llist = (struct lys_node_leaflist *)dev_target;
2809 if (d->mod == LY_DEVIATE_ADD) {
2810 /* reallocate (enlarge) the unique array of the target */
2811 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002812 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002813 } else if (d->mod == LY_DEVIATE_RPL) {
2814 /* reallocate (replace) the unique array of the target */
2815 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002816 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002817 }
2818 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2819 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002820 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002821 }
2822 }
2823 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002824 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002825 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002826 if (c_ext) {
2827 /* some extensions may be already present from the substatements */
2828 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002829 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002830 d->ext = reallocated;
2831
2832 /* init memory */
2833 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2834 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002835
2836 /* process deviation properties with 0..n cardinality */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002837 deviate_must_index = 0;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002838 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2839 if (strcmp(child->ns->value, LY_NSYIN)) {
2840 /* extension */
2841 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2842 goto error;
2843 }
2844 d->ext_size++;
2845 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002846 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002847 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002848 goto error;
2849 }
2850
2851 /* find must to delete, we are ok with just matching conditions */
2852 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002853 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002854 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002855 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002856 /* ... and maintain the array */
2857 (*trg_must_size)--;
2858 if (i != *trg_must_size) {
2859 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2860 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2861 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2862 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2863 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2864 }
2865 if (!(*trg_must_size)) {
2866 free(*trg_must);
2867 *trg_must = NULL;
2868 } else {
2869 (*trg_must)[*trg_must_size].expr = NULL;
2870 (*trg_must)[*trg_must_size].dsc = NULL;
2871 (*trg_must)[*trg_must_size].ref = NULL;
2872 (*trg_must)[*trg_must_size].eapptag = NULL;
2873 (*trg_must)[*trg_must_size].emsg = NULL;
2874 }
2875
2876 i = -1; /* set match flag */
2877 break;
2878 }
2879 }
2880 d->must_size++;
2881 if (i != -1) {
2882 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002883 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002884 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002885 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002886 goto error;
2887 }
2888 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002889 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002890 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002891 goto error;
2892 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05002893 memcpy(d->must + deviate_must_index, &((*trg_must)[*trg_must_size]), sizeof *d->must);
2894 ++deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002895 (*trg_must_size)++;
2896 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002897
2898 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002899 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2900 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002901 goto error;
2902 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002903 } else if (!strcmp(child->name, "unique")) {
2904 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002905 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002906 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002907 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002908 goto error;
2909 }
2910
2911 /* find unique structures to delete */
2912 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002913 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002914 continue;
2915 }
2916
Radek Krejci581ce772015-11-10 17:22:40 +01002917 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002918 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002919 break;
2920 }
2921 }
2922
Radek Krejci581ce772015-11-10 17:22:40 +01002923 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002924 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002925 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002926 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002927 }
2928 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002929 /* ... and maintain the array */
2930 list->unique_size--;
2931 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002932 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2933 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002934 }
2935
2936 if (!list->unique_size) {
2937 free(list->unique);
2938 list->unique = NULL;
2939 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002940 list->unique[list->unique_size].expr_size = 0;
2941 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002942 }
2943
Radek Krejci6bd2c022017-02-01 15:04:49 +01002944 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002945 i = -1; /* set match flag */
2946 break;
2947 }
2948 }
2949
2950 d->unique_size++;
2951 if (i != -1) {
2952 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002953 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2954 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002955 goto error;
2956 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002957
2958 /* remove extensions of this unique instance from the target node */
2959 j = -1;
2960 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 +01002961 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002962 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2963 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002964 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002965 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002966 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002967 }
2968 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002969 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002970 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002971 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002972 list->unique_size++;
2973 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002974 goto error;
2975 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002976 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002977 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002978 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002979 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002980 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002981
2982 if (dev_target->nodetype == LYS_CHOICE) {
2983 choice = (struct lys_node_choice *)dev_target;
2984 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2985 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002986 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002987 goto error;
2988 }
2989 if (d->mod == LY_DEVIATE_DEL) {
2990 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002991 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2992 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002993 goto error;
2994 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002995 choice->dflt = NULL;
2996 /* remove extensions of this default instance from the target node */
2997 j = -1;
2998 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2999 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3000 --j;
3001 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003002 } else { /* add or replace */
3003 choice->dflt = node;
3004 if (!choice->dflt) {
3005 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01003006 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003007 goto error;
3008 }
3009 }
3010 } else if (dev_target->nodetype == LYS_LEAF) {
3011 leaf = (struct lys_node_leaf *)dev_target;
3012 if (d->mod == LY_DEVIATE_DEL) {
3013 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003014 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3015 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003016 goto error;
3017 }
3018 /* remove value */
3019 lydict_remove(ctx, leaf->dflt);
3020 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01003021 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003022
3023 /* remove extensions of this default instance from the target node */
3024 j = -1;
3025 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
3026 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3027 --j;
3028 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003029 } else { /* add (already checked) and replace */
3030 /* remove value */
3031 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01003032 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003033
3034 /* set new value */
3035 leaf->dflt = lydict_insert(ctx, value, u);
3036
Radek Krejcibd117f02016-11-04 16:28:08 +01003037 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02003038 ly_set_add(dflt_check, dev_target, 0);
3039 }
3040 } else { /* LYS_LEAFLIST */
3041 llist = (struct lys_node_leaflist *)dev_target;
3042 if (d->mod == LY_DEVIATE_DEL) {
3043 /* find and remove the value in target list */
3044 for (i = 0; i < llist->dflt_size; i++) {
3045 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
3046 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01003047 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003048 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003049
3050 /* remove extensions of this default instance from the target node */
3051 j = -1;
3052 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 +01003053 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003054 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3055 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003056 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003057 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003058 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003059 }
3060 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003061 break;
3062 }
3063 }
3064 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003065 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3066 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 +02003067 goto error;
3068 }
3069 } else {
3070 /* add or replace, anyway we place items into the deviate's list
3071 which propagates to the target */
3072 /* we just want to check that the value isn't already in the list */
3073 for (i = 0; i < llist->dflt_size; i++) {
3074 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003075 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3076 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003077 goto error;
3078 }
3079 }
3080 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003081 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003082
3083 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3084 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003085 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003086 }
3087 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003088 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003089 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003090
3091 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3092 /* consolidate the final list in the target after removing items from it */
3093 llist = (struct lys_node_leaflist *)dev_target;
3094 for (i = j = 0; j < llist->dflt_size; j++) {
3095 llist->dflt[i] = llist->dflt[j];
3096 if (llist->dflt[i]) {
3097 i++;
3098 }
3099 }
3100 llist->dflt_size = i + 1;
3101 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003102 }
3103
Michal Vasko43a1feb2016-03-07 12:03:02 +01003104 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003105 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003106 for (u = 0; u < dflt_check->number; ++u) {
3107 value = NULL;
3108 rc = EXIT_SUCCESS;
3109 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3110 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3111 value = leaf->dflt;
3112 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3113 } else { /* LYS_LEAFLIST */
3114 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3115 for (j = 0; j < llist->dflt_size; j++) {
3116 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3117 (struct lys_node *)(&llist->dflt[j]));
3118 if (rc == -1) {
3119 value = llist->dflt[j];
3120 break;
3121 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003122 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003123
Michal Vasko15a43372017-09-25 14:12:42 +02003124 }
3125 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003126 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3127 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003128 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3129 dev->target_name);
3130 goto error;
3131 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003132 }
3133 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003134
Radek Krejci27fe55e2016-09-13 17:13:35 +02003135 /* mark all the affected modules as deviated and implemented */
3136 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3137 mod = lys_node_module(parent);
3138 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003139 mod->deviated = 1; /* main module */
3140 parent->module->deviated = 1; /* possible submodule */
Michal Vasko0f437062018-06-08 15:52:39 +02003141 if (!mod->implemented) {
3142 mod->implemented = 1;
3143 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
3144 goto error;
3145 }
Radek Krejci2bb5be72017-02-27 13:07:25 +01003146 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003147 }
3148 }
3149
Radek Krejcid5a5c282016-08-15 15:38:08 +02003150 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003151 return EXIT_SUCCESS;
3152
3153error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003154 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003155 return EXIT_FAILURE;
3156}
3157
Michal Vasko0d343d12015-08-24 14:57:36 +02003158/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003159static int
Radek Krejcib8048692015-08-05 13:36:34 +02003160fill_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 +01003161 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003162{
Michal Vasko53b7da02018-02-13 15:28:42 +01003163 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003165 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003166 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003167 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003168 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003169
Michal Vasko591e0b22015-08-13 13:53:43 +02003170 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003171 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003172 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003173 if (!aug->target_name) {
3174 goto error;
3175 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003177
Radek Krejci07d0fb92017-01-13 14:11:05 +01003178 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003179 goto error;
3180 }
3181
Radek Krejcie534c132016-11-23 13:32:31 +01003182 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3183 if (strcmp(sub->ns->value, LY_NSYIN)) {
3184 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003185 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003186 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003187 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003188 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003189 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003190 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003191 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003192 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003193 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003194 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003195 goto error;
3196 }
3197
Radek Krejci5323b492017-01-16 15:40:11 +01003198 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003199 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003200 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003201 goto error;
3202 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003203 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003204 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003205
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003206 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003207 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003208 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003209 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003210 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003211 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003212 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003213 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003214 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003215 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003216 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003217 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003218 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003219 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003220 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003221 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003222 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003223 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003224 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003225 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003226 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003227 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003228 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003229 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003230 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003231 goto error;
3232 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003233
Radek Krejci1d82ef62015-08-07 14:44:40 +02003234 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003235 goto error;
3236 }
3237
Radek Krejci1d82ef62015-08-07 14:44:40 +02003238 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003239 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003240 }
3241
Radek Krejcie534c132016-11-23 13:32:31 +01003242 if (c_ftrs) {
3243 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003244 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003245 }
Radek Krejcie534c132016-11-23 13:32:31 +01003246 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003247 /* some extensions may be already present from the substatements */
3248 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003249 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003250 aug->ext = reallocated;
3251
3252 /* init memory */
3253 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003254 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003255
Radek Krejcie534c132016-11-23 13:32:31 +01003256 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3257 if (strcmp(sub->ns->value, LY_NSYIN)) {
3258 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003259 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 +01003260 aug->ext_size++;
3261 if (ret) {
3262 goto error;
3263 }
3264 } else if (!strcmp(sub->name, "if-feature")) {
3265 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003266 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003267 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003268 goto error;
3269 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003270 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003271 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003272 }
3273
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003274 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003275 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003276 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003277 * when the uses does and cannot be resolved now for sure
3278 * (the grouping was not yet copied into uses).
3279 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003280 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003281 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003282 goto error;
3283 }
Michal Vasko49291b32015-08-06 09:49:41 +02003284 }
Radek Krejci106efc02015-06-10 14:36:27 +02003285
Michal Vasko508a50d2016-09-07 14:50:33 +02003286 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003287 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003288 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003289 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003290 goto error;
3291 }
3292 } else {
3293 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3294 goto error;
3295 }
3296 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003297 }
3298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003300
3301error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003303}
3304
Michal Vasko0d343d12015-08-24 14:57:36 +02003305/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003307fill_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 +02003308{
Michal Vasko53b7da02018-02-13 15:28:42 +01003309 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003310 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 struct lyxml_elem *sub, *next;
3312 const char *value;
3313 char *endptr;
3314 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003315 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 int r;
3317 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003318 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003319
Radek Krejci363bd4a2016-07-29 14:30:20 +02003320 assert(uses);
3321 module = uses->module; /* shorthand */
3322
Michal Vasko53b7da02018-02-13 15:28:42 +01003323 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003324 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003325 if (!rfn->target_name) {
3326 goto error;
3327 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003330 if (!sub->ns) {
3331 /* garbage */
3332 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003333 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003334 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003335 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003336 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003337
Radek Krejci411b1bf2017-01-23 16:40:05 +01003338 } else if (!strcmp(sub->name, "description")) {
3339 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003340 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003341 goto error;
3342 }
3343
Radek Krejci8d6b7422017-02-03 14:42:13 +01003344 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003345 goto error;
3346 }
3347
Michal Vasko53b7da02018-02-13 15:28:42 +01003348 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003349 if (!rfn->dsc) {
3350 goto error;
3351 }
3352 } else if (!strcmp(sub->name, "reference")) {
3353 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003354 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003355 goto error;
3356 }
3357
Radek Krejci8d6b7422017-02-03 14:42:13 +01003358 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003359 goto error;
3360 }
3361
Michal Vasko53b7da02018-02-13 15:28:42 +01003362 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003363 if (!rfn->ref) {
3364 goto error;
3365 }
3366 } else if (!strcmp(sub->name, "config")) {
3367 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003368 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003369 goto error;
3370 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003371 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003372 if (!strcmp(value, "false")) {
3373 rfn->flags |= LYS_CONFIG_R;
3374 } else if (!strcmp(value, "true")) {
3375 rfn->flags |= LYS_CONFIG_W;
3376 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003377 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003378 goto error;
3379 }
3380 rfn->flags |= LYS_CONFIG_SET;
3381
Radek Krejci8d6b7422017-02-03 14:42:13 +01003382 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003383 goto error;
3384 }
Radek Krejcie534c132016-11-23 13:32:31 +01003385 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003386 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 /* check possibility of statements combination */
3389 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003390 if (c_dflt) {
3391 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003392 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003393 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003394 goto error;
3395 }
Radek Krejci200bf712016-08-16 17:11:04 +02003396 rfn->target_type &= LYS_LEAFLIST;
3397 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003398 if (module->version < 2) {
3399 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3400 } else {
3401 /* YANG 1.1 */
3402 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3403 }
Radek Krejci200bf712016-08-16 17:11:04 +02003404 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003406 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3407 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 goto error;
3409 }
3410 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003411 if (module->version < 2) {
3412 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3413 } else {
3414 /* YANG 1.1 */
3415 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3416 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003418
Michal Vasko53b7da02018-02-13 15:28:42 +01003419 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003420 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 +01003421 goto error;
3422 }
Radek Krejci200bf712016-08-16 17:11:04 +02003423 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003424 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 } else if (!strcmp(sub->name, "mandatory")) {
3426 /* leaf, choice or anyxml */
3427 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003428 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 goto error;
3430 }
3431 /* just checking the flags in leaf is not sufficient, we would allow
3432 * multiple mandatory statements with the "false" value
3433 */
3434 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 /* check possibility of statements combination */
3437 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003438 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003440 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3441 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 goto error;
3443 }
3444 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003445 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003447
Michal Vasko53b7da02018-02-13 15:28:42 +01003448 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003450 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003452 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003454 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 goto error;
3456 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003457 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003458 goto error;
3459 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 } else if (!strcmp(sub->name, "min-elements")) {
3461 /* list or leaf-list */
3462 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003463 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 goto error;
3465 }
3466 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003468 /* check possibility of statements combination */
3469 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003470 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003472 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3473 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 goto error;
3475 }
3476 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003477 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003479
Michal Vasko53b7da02018-02-13 15:28:42 +01003480 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 while (isspace(value[0])) {
3482 value++;
3483 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 /* convert it to uint32_t */
3486 errno = 0;
3487 endptr = NULL;
3488 val = strtoul(value, &endptr, 10);
3489 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003490 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 goto error;
3492 }
3493 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003494 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003495
Radek Krejci8d6b7422017-02-03 14:42:13 +01003496 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003497 goto error;
3498 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 } else if (!strcmp(sub->name, "max-elements")) {
3500 /* list or leaf-list */
3501 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003502 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003503 goto error;
3504 }
3505 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 /* check possibility of statements combination */
3508 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003509 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003511 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3512 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 goto error;
3514 }
3515 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003516 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003518
Michal Vasko53b7da02018-02-13 15:28:42 +01003519 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 while (isspace(value[0])) {
3521 value++;
3522 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003523
Radek Krejci0d7b2472016-02-12 11:11:03 +01003524 if (!strcmp(value, "unbounded")) {
3525 rfn->mod.list.max = 0;
3526 } else {
3527 /* convert it to uint32_t */
3528 errno = 0;
3529 endptr = NULL;
3530 val = strtoul(value, &endptr, 10);
3531 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003532 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003533 goto error;
3534 }
3535 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003537 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003538
Radek Krejci8d6b7422017-02-03 14:42:13 +01003539 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003540 goto error;
3541 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 } else if (!strcmp(sub->name, "presence")) {
3543 /* container */
3544 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003545 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 goto error;
3547 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 /* check possibility of statements combination */
3550 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003551 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003553 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3554 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 goto error;
3556 }
3557 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003558 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003560
Michal Vasko53b7da02018-02-13 15:28:42 +01003561 GETVAL(ctx, value, sub, "value");
3562 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003563
Radek Krejci8d6b7422017-02-03 14:42:13 +01003564 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003565 goto error;
3566 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003568 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003569 /* check possibility of statements combination */
3570 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003571 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003573 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3574 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 goto error;
3576 }
3577 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003578 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003580
Michal Vasko53b7da02018-02-13 15:28:42 +01003581 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003583 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003584
Radek Krejci363bd4a2016-07-29 14:30:20 +02003585 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3586 /* leaf, leaf-list, list, container or anyxml */
3587 /* check possibility of statements combination */
3588 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003589 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003590 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003591 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3592 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003593 goto error;
3594 }
3595 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003596 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003597 }
3598
Michal Vasko53b7da02018-02-13 15:28:42 +01003599 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003600 c_ftrs++;
3601 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003603 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 goto error;
3605 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003606
Michal Vasko53b7da02018-02-13 15:28:42 +01003607 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 /* process nodes with cardinality of 0..n */
3611 if (c_must) {
3612 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003613 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003615 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003616 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003617 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 }
Radek Krejci200bf712016-08-16 17:11:04 +02003619 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003620 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003621 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003622 }
Radek Krejcie534c132016-11-23 13:32:31 +01003623 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003624 /* some extensions may be already present from the substatements */
3625 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003626 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003627 rfn->ext = reallocated;
3628
3629 /* init memory */
3630 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003631 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003632
Radek Krejcie534c132016-11-23 13:32:31 +01003633 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3634 if (strcmp(sub->ns->value, LY_NSYIN)) {
3635 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003636 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 +01003637 rfn->ext_size++;
3638 if (r) {
3639 goto error;
3640 }
3641 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003642 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003643 rfn->iffeature_size++;
3644 if (r) {
3645 goto error;
3646 }
Radek Krejci200bf712016-08-16 17:11:04 +02003647 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003648 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003649 rfn->must_size++;
3650 if (r) {
3651 goto error;
3652 }
Radek Krejci200bf712016-08-16 17:11:04 +02003653 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003654 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003655
3656 /* check for duplicity */
3657 for (r = 0; r < rfn->dflt_size; r++) {
3658 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003659 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3660 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003661 goto error;
3662 }
3663 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003664 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003665 }
3666 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003669
3670error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003672}
3673
Michal Vasko0d343d12015-08-24 14:57:36 +02003674/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675static int
Radek Krejcie534c132016-11-23 13:32:31 +01003676fill_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 +02003677{
Michal Vasko53b7da02018-02-13 15:28:42 +01003678 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003679 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003681 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003682 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003683
Radek Krejcie534c132016-11-23 13:32:31 +01003684 /* init */
3685 memset(&exts, 0, sizeof exts);
3686
3687 LY_TREE_FOR_SAFE(yin->child, next, child) {
3688 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003689 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003690 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003691 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3692 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003693 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003694 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003695 lyxml_unlink_elem(ctx, child, 2);
3696 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003697 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003698 GETVAL(ctx, value, child, "value");
3699 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 goto error;
3701 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003702 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003703
Radek Krejci8d6b7422017-02-03 14:42:13 +01003704 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003705 goto error;
3706 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 } else if (!strcmp(child->name, "revision-date")) {
3708 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003709 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003710 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003712 GETVAL(ctx, value, child, "date");
3713 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 goto error;
3715 }
3716 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003717
Radek Krejci8d6b7422017-02-03 14:42:13 +01003718 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003719 goto error;
3720 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003721 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003722 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003723 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003724 goto error;
3725 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003726 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003727 goto error;
3728 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003729 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003730 if (!imp->dsc) {
3731 goto error;
3732 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003733 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003734 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003735 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003736 goto error;
3737 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003738 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003739 goto error;
3740 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003741 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003742 if (!imp->ref) {
3743 goto error;
3744 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003746 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003747 goto error;
3748 }
3749 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 /* check mandatory information */
3752 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003753 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 goto error;
3755 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003756
Radek Krejcie534c132016-11-23 13:32:31 +01003757 /* process extensions */
3758 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003759 /* some extensions may be already present from the substatements */
3760 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003761 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003762 imp->ext = reallocated;
3763
3764 /* init memory */
3765 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3766
Radek Krejcie534c132016-11-23 13:32:31 +01003767 LY_TREE_FOR_SAFE(exts.child, next, child) {
3768 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003769 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 +01003770 imp->ext_size++;
3771 if (r) {
3772 goto error;
3773 }
3774 }
3775 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003776
Michal Vasko53b7da02018-02-13 15:28:42 +01003777 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003778 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003779
3780error:
Radek Krejcie534c132016-11-23 13:32:31 +01003781 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003782 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003783 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003785}
3786
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003787/* logs directly
3788 * returns:
3789 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003790 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003791 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003793fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3794 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003795{
Michal Vasko53b7da02018-02-13 15:28:42 +01003796 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003797 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003799 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003800 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003801
Radek Krejcie534c132016-11-23 13:32:31 +01003802 /* init */
3803 memset(&exts, 0, sizeof exts);
3804
3805 LY_TREE_FOR_SAFE(yin->child, next, child) {
3806 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003807 /* garbage */
3808 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003809 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3810 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003811 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003812 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003813 lyxml_unlink_elem(ctx, child, 2);
3814 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003815 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003817 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 goto error;
3819 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003820 GETVAL(ctx, value, child, "date");
3821 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 goto error;
3823 }
3824 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003825
Radek Krejci8d6b7422017-02-03 14:42:13 +01003826 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003827 goto error;
3828 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003829 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003830 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003831 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003832 goto error;
3833 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003834 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003835 goto error;
3836 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003837 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003838 if (!inc->dsc) {
3839 goto error;
3840 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003841 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003842 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003843 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003844 goto error;
3845 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003846 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003847 goto error;
3848 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003849 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003850 if (!inc->ref) {
3851 goto error;
3852 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003854 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 goto error;
3856 }
3857 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003858
Radek Krejcie534c132016-11-23 13:32:31 +01003859 /* process extensions */
3860 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003861 /* some extensions may be already present from the substatements */
3862 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003863 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003864 inc->ext = reallocated;
3865
3866 /* init memory */
3867 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3868
Radek Krejcie534c132016-11-23 13:32:31 +01003869 LY_TREE_FOR_SAFE(exts.child, next, child) {
3870 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003871 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 +01003872 inc->ext_size++;
3873 if (r) {
3874 goto error;
3875 }
3876 }
3877 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003878
Michal Vasko53b7da02018-02-13 15:28:42 +01003879 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003880 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003881
3882error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003883 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003884}
3885
Michal Vasko0d343d12015-08-24 14:57:36 +02003886/* logs directly
3887 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003888 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003889 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003890 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003893read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3894 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003895{
Radek Krejcie4dce292017-10-30 11:16:47 +01003896 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 const char *value;
3898 struct lyxml_elem *sub, *next;
3899 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003900 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003903 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003906 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003907 GETVAL(ctx, value, xmlnode, "name");
3908 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003909 goto error;
3910 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003911 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 /* process local parameters */
3915 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003916 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003917 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003918 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003919 continue;
3920 }
3921 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003922 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003923 continue;
3924 }
3925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003927 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003928 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 goto error;
3930 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003931
Radek Krejci8d6b7422017-02-03 14:42:13 +01003932 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003933 goto error;
3934 }
3935
Radek Krejci1d82ef62015-08-07 14:44:40 +02003936 node->dsc = read_yin_subnode(ctx, sub, "text");
3937 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003938 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003939 }
3940 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003942 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 goto error;
3944 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003945
Radek Krejci8d6b7422017-02-03 14:42:13 +01003946 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003947 goto error;
3948 }
3949
Radek Krejci1d82ef62015-08-07 14:44:40 +02003950 node->ref = read_yin_subnode(ctx, sub, "text");
3951 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003952 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 }
3954 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003956 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 goto error;
3958 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003959 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003963 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003967 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003968 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003970
Radek Krejci8d6b7422017-02-03 14:42:13 +01003971 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003972 goto error;
3973 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003974 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3975 if (opt & OPT_CFG_PARSE) {
3976 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003977 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003978 goto error;
3979 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003980 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003981 if (!strcmp(value, "false")) {
3982 node->flags |= LYS_CONFIG_R;
3983 } else if (!strcmp(value, "true")) {
3984 node->flags |= LYS_CONFIG_W;
3985 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003986 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003987 goto error;
3988 }
3989 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003990
Radek Krejci8d6b7422017-02-03 14:42:13 +01003991 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003992 goto error;
3993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003994 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003995 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003996 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003997 continue;
3998 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003999 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004001
Michal Vaskoe022a562016-09-27 14:24:15 +02004002 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02004004 if (parent) {
4005 node->flags |= parent->flags & LYS_CONFIG_MASK;
4006 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004007 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004008 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 }
4010 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004011
Radek Krejci2cc25322017-09-06 16:32:02 +02004012 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
4013 /* status is not inherited by specification, but it not make sense to have
4014 * current in deprecated or deprecated in obsolete, so we print warning
4015 * and fix the schema by inheriting */
4016 if (!(node->flags & (LYS_STATUS_MASK))) {
4017 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01004018 if (stmt_type == LYEXT_PAR_NODE) {
4019 p = node->parent;
4020 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01004021 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004022 node->parent = p;
4023 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01004024 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004025 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004026 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
4027 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02004028 free(str);
4029 node->flags |= parent->flags & LYS_STATUS_MASK;
4030 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
4031 /* invalid combination of statuses */
4032 switch (node->flags & LYS_STATUS_MASK) {
4033 case 0:
4034 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01004035 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004036 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
4037 break;
4038 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01004039 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004040 "obsolete", parent->name);
4041 break;
4042 }
4043 goto error;
4044 }
4045 }
4046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004048
4049error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004051}
4052
Michal Vasko0d343d12015-08-24 14:57:36 +02004053/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004054static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004055read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004056{
Michal Vasko53b7da02018-02-13 15:28:42 +01004057 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004058 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004059 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004060 const char *value;
4061
4062 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004063 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004064
Michal Vasko53b7da02018-02-13 15:28:42 +01004065 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004066 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004067 if (!retval->cond) {
4068 goto error;
4069 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004070
Radek Krejci5323b492017-01-16 15:40:11 +01004071 LY_TREE_FOR_SAFE(yin->child, next, child) {
4072 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004073 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004074 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004075 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4076 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004077 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004078 goto error;
4079 }
4080 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004081 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004082 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004083 goto error;
4084 }
Radek Krejci5323b492017-01-16 15:40:11 +01004085
Radek Krejci8d6b7422017-02-03 14:42:13 +01004086 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004087 goto error;
4088 }
4089
Michal Vasko53b7da02018-02-13 15:28:42 +01004090 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004091 if (!retval->dsc) {
4092 goto error;
4093 }
4094 } else if (!strcmp(child->name, "reference")) {
4095 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004096 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004097 goto error;
4098 }
Radek Krejci5323b492017-01-16 15:40:11 +01004099
Radek Krejci8d6b7422017-02-03 14:42:13 +01004100 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004101 goto error;
4102 }
4103
Michal Vasko53b7da02018-02-13 15:28:42 +01004104 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004105 if (!retval->ref) {
4106 goto error;
4107 }
4108 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004109 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004110 goto error;
4111 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004112 }
4113
4114 return retval;
4115
4116error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004117 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004118 return NULL;
4119}
4120
Michal Vasko0d343d12015-08-24 14:57:36 +02004121/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004122static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004123read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004124 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004125{
Michal Vasko53b7da02018-02-13 15:28:42 +01004126 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004127 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004128 struct lys_node_case *cs;
4129 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004130 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004131 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004132
Radek Krejcie867c852015-08-27 09:52:34 +02004133 /* init */
4134 memset(&root, 0, sizeof root);
4135
Radek Krejci1d82ef62015-08-07 14:44:40 +02004136 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004137 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004138 cs->nodetype = LYS_CASE;
4139 cs->prev = (struct lys_node *)cs;
4140 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004141
Radek Krejci07d0fb92017-01-13 14:11:05 +01004142 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004143 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004144 goto error;
4145 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004146
Michal Vasko3e3228d2017-02-24 14:55:32 +01004147 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004148
Michal Vasko3a0043f2015-08-12 12:11:30 +02004149 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004150 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004151 goto error;
4152 }
4153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 /* process choice's specific children */
4155 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004156 if (strcmp(sub->ns->value, LY_NSYIN)) {
4157 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004158 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004159 c_ext++;
4160 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004161 !strcmp(sub->name, "leaf-list") ||
4162 !strcmp(sub->name, "leaf") ||
4163 !strcmp(sub->name, "list") ||
4164 !strcmp(sub->name, "uses") ||
4165 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004166 !strcmp(sub->name, "anyxml") ||
4167 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004168
Michal Vasko53b7da02018-02-13 15:28:42 +01004169 lyxml_unlink_elem(ctx, sub, 2);
4170 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004171 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004172 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004173 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004174 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004175 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004176 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004177 goto error;
4178 }
4179
Radek Krejci5323b492017-01-16 15:40:11 +01004180 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004181 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004182 goto error;
4183 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004184
Michal Vasko53b7da02018-02-13 15:28:42 +01004185 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004186 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004187 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004188 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004189 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004190 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004191
Radek Krejci3cf9e222015-06-18 11:37:50 +02004192 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004193 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004194 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004195 }
Radek Krejcie534c132016-11-23 13:32:31 +01004196 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004197 /* some extensions may be already present from the substatements */
4198 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004199 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004200 retval->ext = reallocated;
4201
4202 /* init memory */
4203 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004204 }
Radek Krejci21c81652017-01-23 10:42:55 +01004205
Radek Krejcie534c132016-11-23 13:32:31 +01004206 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4207 if (strcmp(sub->ns->value, LY_NSYIN)) {
4208 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004209 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 +01004210 retval->ext_size++;
4211 if (ret) {
4212 goto error;
4213 }
4214 } else {
4215 /* if-feature */
4216 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4217 cs->iffeature_size++;
4218 if (ret) {
4219 goto error;
4220 }
4221 }
4222 }
Radek Krejcib388c152015-06-04 17:03:03 +02004223
Michal Vasko29fc0182015-08-24 15:02:39 +02004224 /* last part - process data nodes */
4225 LY_TREE_FOR_SAFE(root.child, next, sub) {
4226 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004227 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004228 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004229 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004230 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004231 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004232 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004233 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004234 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004235 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004236 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004237 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004238 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004239 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004240 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004241 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004242 }
4243 if (!node) {
4244 goto error;
4245 }
4246
Michal Vasko53b7da02018-02-13 15:28:42 +01004247 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004248 }
4249
Michal Vasko508a50d2016-09-07 14:50:33 +02004250 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004251 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004252 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004253 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004254 goto error;
4255 }
4256 } else {
4257 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4258 goto error;
4259 }
4260 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004261 }
4262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004263 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004264
4265error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004266 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004267 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004268 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004269 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004272}
4273
Michal Vasko0d343d12015-08-24 14:57:36 +02004274/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004275static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004276read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004277 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004278{
Radek Krejci629cdef2016-06-06 15:06:36 +02004279 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004281 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004282 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004283 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004284 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004285 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004287 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004288 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004289
Radek Krejci76512572015-08-04 09:47:08 +02004290 choice->nodetype = LYS_CHOICE;
4291 choice->prev = (struct lys_node *)choice;
4292 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004293
Radek Krejci07d0fb92017-01-13 14:11:05 +01004294 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004295 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4296 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4297 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 goto error;
4299 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004300
Michal Vasko3e3228d2017-02-24 14:55:32 +01004301 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004302
Michal Vasko3a0043f2015-08-12 12:11:30 +02004303 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004304 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004305 goto error;
4306 }
4307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 /* process choice's specific children */
4309 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004310 if (strcmp(sub->ns->value, LY_NSYIN)) {
4311 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004312 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004313 c_ext++;
4314 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004315 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004316 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004317 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004318 goto error;
4319 }
4320 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004321 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004322 goto error;
4323 }
4324 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004325 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326 goto error;
4327 }
4328 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004329 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 goto error;
4331 }
4332 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004333 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 goto error;
4335 }
4336 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004337 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004338 goto error;
4339 }
4340 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004341 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 goto error;
4343 }
4344 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004345 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004346 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004347 goto error;
4348 }
Radek Krejci21c81652017-01-23 10:42:55 +01004349
Radek Krejci8d6b7422017-02-03 14:42:13 +01004350 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004351 goto error;
4352 }
4353
Radek Krejci629cdef2016-06-06 15:06:36 +02004354 dflt = sub;
4355 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004356 continue;
4357 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004359 } else if (!strcmp(sub->name, "mandatory")) {
4360 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004361 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 goto error;
4363 }
4364 /* just checking the flags in leaf is not sufficient, we would allow
4365 * multiple mandatory statements with the "false" value
4366 */
4367 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004368
Michal Vasko53b7da02018-02-13 15:28:42 +01004369 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004371 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004372 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004373 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004374 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004375 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 goto error;
4377 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004378
Radek Krejci8d6b7422017-02-03 14:42:13 +01004379 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004380 goto error;
4381 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004382 } else if (!strcmp(sub->name, "when")) {
4383 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004384 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004385 goto error;
4386 }
4387
Radek Krejci5323b492017-01-16 15:40:11 +01004388 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004389 if (!choice->when) {
4390 goto error;
4391 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004392 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004393 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004394 c_ftrs++;
4395
Michal Vasko345da0a2015-12-02 10:35:55 +01004396 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004397 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004398 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004399 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004400 goto error;
4401 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004403 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004406
Radek Krejci1d82ef62015-08-07 14:44:40 +02004407 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004408 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004410
Radek Krejci3cf9e222015-06-18 11:37:50 +02004411 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004412 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004413 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004414 }
Radek Krejcie534c132016-11-23 13:32:31 +01004415 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004416 /* some extensions may be already present from the substatements */
4417 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004418 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004419 retval->ext = reallocated;
4420
4421 /* init memory */
4422 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004423 }
4424
Radek Krejcie534c132016-11-23 13:32:31 +01004425 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4426 if (strcmp(sub->ns->value, LY_NSYIN)) {
4427 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004428 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 +01004429 retval->ext_size++;
4430 if (ret) {
4431 goto error;
4432 }
4433 } else {
4434 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4435 choice->iffeature_size++;
4436 if (ret) {
4437 goto error;
4438 }
4439 }
4440 }
4441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004442 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004443 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004444 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4445 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 goto error;
4447 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004449 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004450 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004451 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004452 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004453 goto error;
4454 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004455 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004456 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004457
Michal Vasko508a50d2016-09-07 14:50:33 +02004458 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004459 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004460 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004461 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004462 goto error;
4463 }
4464 } else {
4465 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4466 goto error;
4467 }
4468 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004469 }
4470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004472
4473error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004474 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004475 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004477}
4478
Michal Vasko0d343d12015-08-24 14:57:36 +02004479/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004480static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004481read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004482 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004483{
Michal Vasko53b7da02018-02-13 15:28:42 +01004484 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004485 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004486 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004487 struct lyxml_elem *sub, *next;
4488 const char *value;
4489 int r;
4490 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004491 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004492 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004495 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004496
Radek Krejcibf2abff2016-08-23 15:51:52 +02004497 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004498 anyxml->prev = (struct lys_node *)anyxml;
4499 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004500
Radek Krejci07d0fb92017-01-13 14:11:05 +01004501 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004502 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004503 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 goto error;
4505 }
Radek Krejci863c2852015-06-03 15:47:11 +02004506
Michal Vasko3e3228d2017-02-24 14:55:32 +01004507 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004508
Radek Krejcic189a952016-07-11 15:27:07 +02004509 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004510 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004511 goto error;
4512 }
4513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004515 if (strcmp(sub->ns->value, LY_NSYIN)) {
4516 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004517 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004518 c_ext++;
4519 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004521 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 goto error;
4523 }
4524 /* just checking the flags in leaf is not sufficient, we would allow
4525 * multiple mandatory statements with the "false" value
4526 */
4527 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004528
Michal Vasko53b7da02018-02-13 15:28:42 +01004529 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004531 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004532 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004533 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004534 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004535 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 goto error;
4537 }
4538 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004539
Radek Krejci8d6b7422017-02-03 14:42:13 +01004540 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004541 goto error;
4542 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004543 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004544 } else if (!strcmp(sub->name, "when")) {
4545 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004546 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004547 goto error;
4548 }
4549
Radek Krejci5323b492017-01-16 15:40:11 +01004550 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004551 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004552 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004553 goto error;
4554 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004555 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004557 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004559 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004560 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004561 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004562
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004564 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004565 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 }
4567 }
Radek Krejci863c2852015-06-03 15:47:11 +02004568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 /* middle part - process nodes with cardinality of 0..n */
4570 if (c_must) {
4571 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004572 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004574 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004575 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004576 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004577 }
Radek Krejcie534c132016-11-23 13:32:31 +01004578 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004579 /* some extensions may be already present from the substatements */
4580 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004581 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004582 retval->ext = reallocated;
4583
4584 /* init memory */
4585 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004586 }
Radek Krejci863c2852015-06-03 15:47:11 +02004587
Radek Krejcie534c132016-11-23 13:32:31 +01004588 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4589 if (strcmp(sub->ns->value, LY_NSYIN)) {
4590 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004591 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 +01004592 retval->ext_size++;
4593 if (r) {
4594 goto error;
4595 }
4596 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004597 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004598 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 if (r) {
4600 goto error;
4601 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004602 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004603 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004604 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004605 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004606 goto error;
4607 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004608 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 }
Radek Krejci863c2852015-06-03 15:47:11 +02004610
Michal Vasko508a50d2016-09-07 14:50:33 +02004611 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004612 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004613 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004614 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004615 goto error;
4616 }
4617 } else {
4618 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4619 goto error;
4620 }
4621 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004622 }
4623
PavolVican92f23622017-12-12 13:35:56 +01004624 for (r = 0; r < retval->ext_size; ++r) {
4625 /* set flag, which represent LYEXT_OPT_VALID */
4626 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004627 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004628 break;
4629 }
4630 }
4631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004633
4634error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004635 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004637}
4638
Michal Vasko0d343d12015-08-24 14:57:36 +02004639/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004640static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004641read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004642 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004643{
Michal Vasko53b7da02018-02-13 15:28:42 +01004644 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004645 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004646 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 struct lyxml_elem *sub, *next;
4648 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004649 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004650 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004651 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004654 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004655
Radek Krejci76512572015-08-04 09:47:08 +02004656 leaf->nodetype = LYS_LEAF;
4657 leaf->prev = (struct lys_node *)leaf;
4658 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004659
Radek Krejci07d0fb92017-01-13 14:11:05 +01004660 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004661 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4662 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4663 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664 goto error;
4665 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004666
Michal Vasko3e3228d2017-02-24 14:55:32 +01004667 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004668
Radek Krejcic189a952016-07-11 15:27:07 +02004669 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004670 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004671 goto error;
4672 }
4673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004675 if (strcmp(sub->ns->value, LY_NSYIN)) {
4676 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004677 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004678 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004679 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004680 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004681 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004682 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 goto error;
4684 }
Michal Vasko88c29542015-11-27 14:57:53 +01004685 /* HACK for unres */
4686 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004687 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004688 /* postpone type resolution when if-feature parsing is done since we need
4689 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004690 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 } else if (!strcmp(sub->name, "default")) {
4692 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004693 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 goto error;
4695 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004696 GETVAL(ctx, value, sub, "value");
4697 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004698
Radek Krejci8d6b7422017-02-03 14:42:13 +01004699 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004700 goto error;
4701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 } else if (!strcmp(sub->name, "units")) {
4703 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004704 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004705 goto error;
4706 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004707 GETVAL(ctx, value, sub, "name");
4708 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004709
Radek Krejci8d6b7422017-02-03 14:42:13 +01004710 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004711 goto error;
4712 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 } else if (!strcmp(sub->name, "mandatory")) {
4714 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004715 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 goto error;
4717 }
4718 /* just checking the flags in leaf is not sufficient, we would allow
4719 * multiple mandatory statements with the "false" value
4720 */
4721 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004722
Michal Vasko53b7da02018-02-13 15:28:42 +01004723 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004725 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004726 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004727 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004728 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004729 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 goto error;
4731 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004732
Radek Krejci8d6b7422017-02-03 14:42:13 +01004733 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004734 goto error;
4735 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004736 } else if (!strcmp(sub->name, "when")) {
4737 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004738 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004739 goto error;
4740 }
4741
Radek Krejci5323b492017-01-16 15:40:11 +01004742 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004743 if (!leaf->when) {
4744 goto error;
4745 }
4746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004748 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004749 c_must++;
4750 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004751 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004752 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004753 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004757 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004759 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004760
Michal Vasko88c29542015-11-27 14:57:53 +01004761 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004762 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004765 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004766 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 goto error;
4768 }
Michal Vasko478c4652016-07-21 12:55:01 +02004769 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004770 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4771 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004772 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4773 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 /* middle part - process nodes with cardinality of 0..n */
4777 if (c_must) {
4778 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004779 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004781 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004782 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004783 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004784 }
Radek Krejcie534c132016-11-23 13:32:31 +01004785 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004786 /* some extensions may be already present from the substatements */
4787 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004788 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004789 retval->ext = reallocated;
4790
4791 /* init memory */
4792 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004793 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004794
Radek Krejcie534c132016-11-23 13:32:31 +01004795 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4796 if (strcmp(sub->ns->value, LY_NSYIN)) {
4797 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004798 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004799 retval->ext_size++;
4800 if (r) {
4801 goto error;
4802 }
4803 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004804 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004805 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 if (r) {
4807 goto error;
4808 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004809 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004810 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004811 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004812 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004813 goto error;
4814 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004817
Radek Krejcicbb473e2016-09-16 14:48:32 +02004818 /* finalize type parsing */
4819 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4820 leaf->type.der = NULL;
4821 goto error;
4822 }
4823
4824 /* check default value (if not defined, there still could be some restrictions
4825 * that need to be checked against a default value from a derived type) */
Michal Vasko6a057782018-03-09 13:24:33 +01004826 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004827 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4828 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004829 goto error;
4830 }
4831
Michal Vasko508a50d2016-09-07 14:50:33 +02004832 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004833 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004834 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004835 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004836 goto error;
4837 }
4838 } else {
4839 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4840 goto error;
4841 }
4842 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004843 }
4844
PavolVican92f23622017-12-12 13:35:56 +01004845 for (r = 0; r < retval->ext_size; ++r) {
4846 /* set flag, which represent LYEXT_OPT_VALID */
4847 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004848 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004849 break;
4850 }
4851 }
4852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004853 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004854
4855error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004856 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004858}
4859
Michal Vasko0d343d12015-08-24 14:57:36 +02004860/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004861static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004862read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004863 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004864{
Michal Vasko53b7da02018-02-13 15:28:42 +01004865 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004866 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004867 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 struct lyxml_elem *sub, *next;
4869 const char *value;
4870 char *endptr;
4871 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004872 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004873 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004875 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004878 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004879
Radek Krejci76512572015-08-04 09:47:08 +02004880 llist->nodetype = LYS_LEAFLIST;
4881 llist->prev = (struct lys_node *)llist;
4882 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004883
Radek Krejci07d0fb92017-01-13 14:11:05 +01004884 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004885 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4886 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4887 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 goto error;
4889 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004890
Michal Vasko3e3228d2017-02-24 14:55:32 +01004891 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004892
Radek Krejcic189a952016-07-11 15:27:07 +02004893 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004894 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004895 goto error;
4896 }
4897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004899 if (strcmp(sub->ns->value, LY_NSYIN)) {
4900 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004901 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004902 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004903 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004904 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004905 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004906 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004907 goto error;
4908 }
Michal Vasko88c29542015-11-27 14:57:53 +01004909 /* HACK for unres */
4910 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004911 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004912 /* postpone type resolution when if-feature parsing is done since we need
4913 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004914 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 } else if (!strcmp(sub->name, "units")) {
4916 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004917 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004918 goto error;
4919 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004920 GETVAL(ctx, value, sub, "name");
4921 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004922
Radek Krejci8d6b7422017-02-03 14:42:13 +01004923 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004924 goto error;
4925 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004926 } else if (!strcmp(sub->name, "ordered-by")) {
4927 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004928 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 goto error;
4930 }
4931 /* just checking the flags in llist is not sufficient, we would
4932 * allow multiple ordered-by statements with the "system" value
4933 */
4934 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004935
Radek Krejci1574a8d2015-08-03 14:16:52 +02004936 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4938 * state data
4939 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004940 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004941 continue;
4942 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004943
Michal Vasko53b7da02018-02-13 15:28:42 +01004944 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004946 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004948 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004949 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004950 } /* else system is the default value, so we can ignore it */
4951
Radek Krejci8d6b7422017-02-03 14:42:13 +01004952 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004953 goto error;
4954 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004956 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004957 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004958 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004959 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004960 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004961 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004962 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004963 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004964 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004965 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 +01004966 goto error;
4967 }
4968
Michal Vasko53b7da02018-02-13 15:28:42 +01004969 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004970 c_dflt++;
4971 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004973 } else if (!strcmp(sub->name, "min-elements")) {
4974 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004975 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 goto error;
4977 }
4978 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004979
Michal Vasko53b7da02018-02-13 15:28:42 +01004980 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004981 while (isspace(value[0])) {
4982 value++;
4983 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 /* convert it to uint32_t */
4986 errno = 0;
4987 endptr = NULL;
4988 val = strtoul(value, &endptr, 10);
4989 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004990 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 goto error;
4992 }
4993 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004994 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004995 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4996 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004997 goto error;
4998 }
Radek Krejci5323b492017-01-16 15:40:11 +01004999
Radek Krejci8d6b7422017-02-03 14:42:13 +01005000 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005001 goto error;
5002 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 } else if (!strcmp(sub->name, "max-elements")) {
5004 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005005 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 goto error;
5007 }
5008 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005009
Michal Vasko53b7da02018-02-13 15:28:42 +01005010 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005011 while (isspace(value[0])) {
5012 value++;
5013 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005014
Radek Krejci0d7b2472016-02-12 11:11:03 +01005015 if (!strcmp(value, "unbounded")) {
5016 llist->max = 0;
5017 } else {
5018 /* convert it to uint32_t */
5019 errno = 0;
5020 endptr = NULL;
5021 val = strtoul(value, &endptr, 10);
5022 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005023 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005024 goto error;
5025 }
5026 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005027 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005028 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5029 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005030 goto error;
5031 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 }
Radek Krejci5323b492017-01-16 15:40:11 +01005033
Radek Krejci8d6b7422017-02-03 14:42:13 +01005034 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005035 goto error;
5036 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005037 } else if (!strcmp(sub->name, "when")) {
5038 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005039 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005040 goto error;
5041 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005042
Radek Krejci5323b492017-01-16 15:40:11 +01005043 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005044 if (!llist->when) {
5045 goto error;
5046 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005048 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005051
Michal Vasko88c29542015-11-27 14:57:53 +01005052 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005053 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005056 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005057 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005058 goto error;
5059 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005061 /* middle part - process nodes with cardinality of 0..n */
5062 if (c_must) {
5063 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005064 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005066 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005067 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005068 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005069 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005070 if (c_dflt) {
5071 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005072 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005073 }
Radek Krejcie534c132016-11-23 13:32:31 +01005074 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005075 /* some extensions may be already present from the substatements */
5076 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005077 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005078 retval->ext = reallocated;
5079
5080 /* init memory */
5081 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005082 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005083
Radek Krejcie534c132016-11-23 13:32:31 +01005084 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5085 if (strcmp(sub->ns->value, LY_NSYIN)) {
5086 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005087 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 +01005088 retval->ext_size++;
5089 if (r) {
5090 goto error;
5091 }
5092 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005093 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005094 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005095 if (r) {
5096 goto error;
5097 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005098 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005099 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005100 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005101 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005102 goto error;
5103 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005104 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005105 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005106
Radek Krejciac1a52c2016-09-15 14:42:40 +02005107 /* check for duplicity in case of configuration data,
5108 * in case of status data duplicities are allowed */
5109 if (llist->flags & LYS_CONFIG_W) {
5110 for (r = 0; r < llist->dflt_size; r++) {
5111 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005112 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5113 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005114 goto error;
5115 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005116 }
5117 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005118 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005119 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005120 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005121
Radek Krejcicbb473e2016-09-16 14:48:32 +02005122 /* finalize type parsing */
5123 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5124 llist->type.der = NULL;
5125 goto error;
5126 }
5127
Radek Krejcid5a5c282016-08-15 15:38:08 +02005128 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005129 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5130 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005131 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5132 goto error;
5133 }
5134
5135 /* check default value (if not defined, there still could be some restrictions
5136 * that need to be checked against a default value from a derived type) */
5137 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko6a057782018-03-09 13:24:33 +01005138 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005139 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5140 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005141 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005142 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005143 }
5144
Michal Vasko508a50d2016-09-07 14:50:33 +02005145 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005146 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005147 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005148 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005149 goto error;
5150 }
5151 } else {
5152 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5153 goto error;
5154 }
5155 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005156 }
5157
PavolVican92f23622017-12-12 13:35:56 +01005158 for (r = 0; r < retval->ext_size; ++r) {
5159 /* set flag, which represent LYEXT_OPT_VALID */
5160 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005161 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005162 break;
5163 }
5164 }
5165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005166 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005167
5168error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005169 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005170 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005171}
5172
Michal Vasko0d343d12015-08-24 14:57:36 +02005173/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005174static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005175read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005176 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005177{
Michal Vasko53b7da02018-02-13 15:28:42 +01005178 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005179 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005180 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005182 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005183 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005184 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005185 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005186 char *auxs;
5187 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005188 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 /* init */
5191 memset(&root, 0, sizeof root);
5192 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005194 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005195 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005196
Radek Krejci76512572015-08-04 09:47:08 +02005197 list->nodetype = LYS_LIST;
5198 list->prev = (struct lys_node *)list;
5199 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005200
Radek Krejci07d0fb92017-01-13 14:11:05 +01005201 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005202 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5203 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5204 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 goto error;
5206 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005207
Michal Vasko3e3228d2017-02-24 14:55:32 +01005208 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005209
Radek Krejcic189a952016-07-11 15:27:07 +02005210 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005211 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005212 goto error;
5213 }
5214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005215 /* process list's specific children */
5216 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005217 if (strcmp(sub->ns->value, LY_NSYIN)) {
5218 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005219 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005220 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005221 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005224 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 !strcmp(sub->name, "leaf-list") ||
5226 !strcmp(sub->name, "leaf") ||
5227 !strcmp(sub->name, "list") ||
5228 !strcmp(sub->name, "choice") ||
5229 !strcmp(sub->name, "uses") ||
5230 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005231 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005232 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005233 !strcmp(sub->name, "action") ||
5234 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005235 lyxml_unlink_elem(ctx, sub, 2);
5236 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005238 /* array counters */
5239 } else if (!strcmp(sub->name, "key")) {
5240 /* check cardinality 0..1 */
5241 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005242 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243 goto error;
5244 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005246 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005247 GETVAL(ctx, value, sub, "value");
5248 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 while ((value = strpbrk(value, " \t\n"))) {
5250 list->keys_size++;
5251 while (isspace(*value)) {
5252 value++;
5253 }
5254 }
5255 list->keys_size++;
5256 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005257 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005258
Radek Krejci8d6b7422017-02-03 14:42:13 +01005259 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005260 goto error;
5261 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005262 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005264 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005265 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005266 lyxml_unlink_elem(ctx, sub, 2);
5267 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005269 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 c_tpdf++;
5271 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005272 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005274 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005275 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005276 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 /* optional stetments */
5279 } else if (!strcmp(sub->name, "ordered-by")) {
5280 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005281 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005282 goto error;
5283 }
5284 /* just checking the flags in llist is not sufficient, we would
5285 * allow multiple ordered-by statements with the "system" value
5286 */
5287 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005288
Radek Krejci1574a8d2015-08-03 14:16:52 +02005289 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005290 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5291 * state data
5292 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005293 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005294 continue;
5295 }
Radek Krejci345ad742015-06-03 11:04:18 +02005296
Michal Vasko53b7da02018-02-13 15:28:42 +01005297 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005299 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005301 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005302 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005303 } /* else system is the default value, so we can ignore it */
5304
Radek Krejci8d6b7422017-02-03 14:42:13 +01005305 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005306 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005307 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005308 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005309 } else if (!strcmp(sub->name, "min-elements")) {
5310 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005311 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 goto error;
5313 }
5314 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005315
Michal Vasko53b7da02018-02-13 15:28:42 +01005316 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005317 while (isspace(value[0])) {
5318 value++;
5319 }
Radek Krejci345ad742015-06-03 11:04:18 +02005320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005321 /* convert it to uint32_t */
5322 errno = 0;
5323 auxs = NULL;
5324 val = strtoul(value, &auxs, 10);
5325 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005326 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005327 goto error;
5328 }
5329 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005330 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005331 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5332 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5333 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005334 goto error;
5335 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005336 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005337 goto error;
5338 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005339 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 } else if (!strcmp(sub->name, "max-elements")) {
5341 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005342 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005343 goto error;
5344 }
5345 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005346
Michal Vasko53b7da02018-02-13 15:28:42 +01005347 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005348 while (isspace(value[0])) {
5349 value++;
5350 }
Radek Krejci345ad742015-06-03 11:04:18 +02005351
Radek Krejci0d7b2472016-02-12 11:11:03 +01005352 if (!strcmp(value, "unbounded")) {
5353 list->max = 0;;
5354 } else {
5355 /* convert it to uint32_t */
5356 errno = 0;
5357 auxs = NULL;
5358 val = strtoul(value, &auxs, 10);
5359 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005360 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005361 goto error;
5362 }
5363 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005364 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005365 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5366 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005367 goto error;
5368 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005370 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005371 goto error;
5372 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005373 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005374 } else if (!strcmp(sub->name, "when")) {
5375 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005376 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005377 goto error;
5378 }
5379
Radek Krejci5323b492017-01-16 15:40:11 +01005380 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005381 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005382 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005383 goto error;
5384 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005385 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005386 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005387 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005388 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005389 }
5390 }
Radek Krejci345ad742015-06-03 11:04:18 +02005391
Michal Vaskoe022a562016-09-27 14:24:15 +02005392 /* check - if list is configuration, key statement is mandatory
5393 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005394 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005395 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005396 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 goto error;
5398 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005400 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5401 if (c_tpdf) {
5402 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005403 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005404 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005405 if (c_must) {
5406 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005407 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005408 }
5409 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005410 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005411 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005412 }
Radek Krejcie534c132016-11-23 13:32:31 +01005413 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005414 /* some extensions may be already present from the substatements */
5415 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005416 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005417 retval->ext = reallocated;
5418
5419 /* init memory */
5420 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005421 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005422
Radek Krejcie534c132016-11-23 13:32:31 +01005423 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5424 if (strcmp(sub->ns->value, LY_NSYIN)) {
5425 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005426 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 +01005427 retval->ext_size++;
5428 if (r) {
5429 goto error;
5430 }
5431 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005432 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5433 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005434 if (r) {
5435 goto error;
5436 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005437 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005438 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005439 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005440 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005441 goto error;
5442 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005443 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005444 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005445 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005446 if (r) {
5447 goto error;
5448 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005449 }
5450 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005452 /* last part - process data nodes */
5453 LY_TREE_FOR_SAFE(root.child, next, sub) {
5454 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005455 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005456 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005457 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005458 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005459 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005460 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005461 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005462 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005463 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005464 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005465 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005466 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005467 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005468 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005469 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005470 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005471 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005472 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005473 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005474 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005475 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005476 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005477 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005478 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005479 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005480 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005481 goto error;
5482 }
Radek Krejci73adb602015-07-02 18:07:40 +02005483
Michal Vasko53b7da02018-02-13 15:28:42 +01005484 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005485 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005486
Radek Krejci5c08a992016-11-02 13:30:04 +01005487 if (list->keys_str) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02005488 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005489 goto error;
5490 }
5491 } /* 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 +02005492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005493 /* process unique statements */
5494 if (c_uniq) {
5495 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005496 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005497
Radek Krejci461efb92016-02-12 15:52:18 +01005498 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5499 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5500 list->unique_size++;
5501 if (r) {
5502 goto error;
5503 }
5504
Radek Krejci8d6b7422017-02-03 14:42:13 +01005505 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005506 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5507 goto error;
5508 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005509 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005510 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005511 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005512
Michal Vasko508a50d2016-09-07 14:50:33 +02005513 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005514 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005515 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005516 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005517 goto error;
5518 }
5519 } else {
5520 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5521 goto error;
5522 }
5523 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005524 }
5525
PavolVican92f23622017-12-12 13:35:56 +01005526 for (r = 0; r < retval->ext_size; ++r) {
5527 /* set flag, which represent LYEXT_OPT_VALID */
5528 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005529 retval->flags |= LYS_VALID_EXT;
Robin Jarry8d820d32019-04-06 12:26:13 +02005530 if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
5531 retval->flags |= LYS_VALID_EXT_SUBTREE;
5532 break;
5533 }
PavolVican92f23622017-12-12 13:35:56 +01005534 }
5535 }
5536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005537 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005538
5539error:
5540
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005541 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005542 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005543 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005544 }
5545 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005546 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005547 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005549 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005550}
5551
Michal Vasko0d343d12015-08-24 14:57:36 +02005552/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005553static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005554read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005555 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005556{
Michal Vasko53b7da02018-02-13 15:28:42 +01005557 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005558 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005559 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005560 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005561 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005563 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005564 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005565 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005567 /* init */
5568 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005570 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005571 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005572
Radek Krejci76512572015-08-04 09:47:08 +02005573 cont->nodetype = LYS_CONTAINER;
5574 cont->prev = (struct lys_node *)cont;
5575 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005576
Radek Krejci07d0fb92017-01-13 14:11:05 +01005577 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005578 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5579 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5580 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005581 goto error;
5582 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005583
Michal Vasko3e3228d2017-02-24 14:55:32 +01005584 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005585
Radek Krejcic189a952016-07-11 15:27:07 +02005586 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005587 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005588 goto error;
5589 }
5590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005591 /* process container's specific children */
5592 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005593 if (strcmp(sub->ns->value, LY_NSYIN)) {
5594 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005595 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005596 c_ext++;
5597 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005598 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005599 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005600 goto error;
5601 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005602 GETVAL(ctx, value, sub, "value");
5603 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005604
Radek Krejci8d6b7422017-02-03 14:42:13 +01005605 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005606 goto error;
5607 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005608 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005609 } else if (!strcmp(sub->name, "when")) {
5610 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005611 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005612 goto error;
5613 }
5614
Radek Krejci5323b492017-01-16 15:40:11 +01005615 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005616 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005617 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005618 goto error;
5619 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005620 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005622 /* data statements */
5623 } else if (!strcmp(sub->name, "container") ||
5624 !strcmp(sub->name, "leaf-list") ||
5625 !strcmp(sub->name, "leaf") ||
5626 !strcmp(sub->name, "list") ||
5627 !strcmp(sub->name, "choice") ||
5628 !strcmp(sub->name, "uses") ||
5629 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005630 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005631 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005632 !strcmp(sub->name, "action") ||
5633 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005634 lyxml_unlink_elem(ctx, sub, 2);
5635 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005637 /* array counters */
5638 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005639 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005640 c_tpdf++;
5641 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005642 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005643 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005644 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005645 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005646 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005647 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005648 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005649 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005650 }
5651 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005653 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5654 if (c_tpdf) {
5655 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005656 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005657 }
5658 if (c_must) {
5659 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005660 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005661 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005662 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005663 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005664 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005665 }
Radek Krejcie534c132016-11-23 13:32:31 +01005666 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005667 /* some extensions may be already present from the substatements */
5668 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005669 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005670 retval->ext = reallocated;
5671
5672 /* init memory */
5673 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005674 }
Radek Krejci800af702015-06-02 13:46:01 +02005675
Radek Krejcie534c132016-11-23 13:32:31 +01005676 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5677 if (strcmp(sub->ns->value, LY_NSYIN)) {
5678 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005679 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 +01005680 retval->ext_size++;
5681 if (r) {
5682 goto error;
5683 }
5684 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005685 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5686 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005687 if (r) {
5688 goto error;
5689 }
5690 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005691 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005692 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005693 if (r) {
5694 goto error;
5695 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005696 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005697 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005698 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005699 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005700 goto error;
5701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005703 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005705 /* last part - process data nodes */
5706 LY_TREE_FOR_SAFE(root.child, next, sub) {
5707 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005708 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005709 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005710 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005711 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005712 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005713 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005714 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005715 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005716 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005717 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005718 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005719 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005720 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005721 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005722 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005723 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005724 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005725 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005726 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005727 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005728 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005730 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005731 goto error;
5732 }
Radek Krejci73adb602015-07-02 18:07:40 +02005733
Michal Vasko53b7da02018-02-13 15:28:42 +01005734 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005735 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005736
Michal Vasko508a50d2016-09-07 14:50:33 +02005737 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005738 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005739 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005740 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005741 goto error;
5742 }
5743 } else {
5744 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5745 goto error;
5746 }
5747 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005748 }
5749
PavolVican92f23622017-12-12 13:35:56 +01005750 for (r = 0; r < retval->ext_size; ++r) {
5751 /* set flag, which represent LYEXT_OPT_VALID */
5752 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005753 retval->flags |= LYS_VALID_EXT;
Robin Jarry8d820d32019-04-06 12:26:13 +02005754 if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
5755 retval->flags |= LYS_VALID_EXT_SUBTREE;
5756 break;
5757 }
PavolVican92f23622017-12-12 13:35:56 +01005758 }
5759 }
5760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005761 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005762
5763error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005764 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005765 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005766 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005768 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005769}
5770
Michal Vasko0d343d12015-08-24 14:57:36 +02005771/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005772static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005773read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005774 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005775{
Michal Vasko53b7da02018-02-13 15:28:42 +01005776 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005777 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005778 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005779 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005780 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005781 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005782 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005783 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005785 /* init */
5786 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005788 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005789 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005790
Radek Krejci76512572015-08-04 09:47:08 +02005791 grp->nodetype = LYS_GROUPING;
5792 grp->prev = (struct lys_node *)grp;
5793 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005794
Radek Krejci07d0fb92017-01-13 14:11:05 +01005795 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005796 goto error;
5797 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005798
Michal Vasko3e3228d2017-02-24 14:55:32 +01005799 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005800
Radek Krejcic189a952016-07-11 15:27:07 +02005801 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005802 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005803 goto error;
5804 }
5805
Radek Krejci1d82ef62015-08-07 14:44:40 +02005806 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005807 if (strcmp(sub->ns->value, LY_NSYIN)) {
5808 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005809 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005810 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005812 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005813 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005814 !strcmp(sub->name, "leaf-list") ||
5815 !strcmp(sub->name, "leaf") ||
5816 !strcmp(sub->name, "list") ||
5817 !strcmp(sub->name, "choice") ||
5818 !strcmp(sub->name, "uses") ||
5819 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005820 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005821 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005822 !strcmp(sub->name, "action") ||
5823 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005824 lyxml_unlink_elem(ctx, sub, 2);
5825 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005827 /* array counters */
5828 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005829 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005830 c_tpdf++;
5831 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005832 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005833 goto error;
5834 }
5835 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005837 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5838 if (c_tpdf) {
5839 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005840 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005841 }
Radek Krejcie534c132016-11-23 13:32:31 +01005842 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005843 /* some extensions may be already present from the substatements */
5844 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005845 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005846 retval->ext = reallocated;
5847
5848 /* init memory */
5849 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005850 }
Radek Krejcie534c132016-11-23 13:32:31 +01005851 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5852 if (strcmp(sub->ns->value, LY_NSYIN)) {
5853 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005854 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 +01005855 retval->ext_size++;
5856 if (r) {
5857 goto error;
5858 }
5859 } else {
5860 /* typedef */
5861 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5862 grp->tpdf_size++;
5863 if (r) {
5864 goto error;
5865 }
5866 }
5867 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005869 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005870 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005871 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005872 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005873 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005874 LY_TREE_FOR_SAFE(root.child, next, sub) {
5875 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005876 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005877 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005878 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005879 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005880 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005881 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005882 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005883 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005884 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005885 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005886 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005887 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005888 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005889 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005890 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005891 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005892 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005893 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005894 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005895 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005896 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005897 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005898 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005899 goto error;
5900 }
Radek Krejci73adb602015-07-02 18:07:40 +02005901
Michal Vasko53b7da02018-02-13 15:28:42 +01005902 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005903 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005905 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005906
5907error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005908 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005909 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005910 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005911 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005912 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005913}
5914
Michal Vasko0d343d12015-08-24 14:57:36 +02005915/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005916static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005917read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005918 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005919{
Michal Vasko53b7da02018-02-13 15:28:42 +01005920 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005921 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005922 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005923 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005924 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005925 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005926 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005927
Radek Krejcie0674f82015-06-15 13:58:51 +02005928 /* init */
5929 memset(&root, 0, sizeof root);
5930
Michal Vasko38d01f72015-06-15 09:41:06 +02005931 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005932 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005933 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005934
5935 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005936 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005937 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005938 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005939 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005940 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005941 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005942 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005943 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005944 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005945 }
5946
Radek Krejci76512572015-08-04 09:47:08 +02005947 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005948 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005949
Michal Vasko3e3228d2017-02-24 14:55:32 +01005950 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005951
Radek Krejcic189a952016-07-11 15:27:07 +02005952 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005953 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005954 goto error;
5955 }
5956
Michal Vasko38d01f72015-06-15 09:41:06 +02005957 /* data statements */
5958 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005959 if (!sub->ns) {
5960 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005961 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005962 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005963 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005964 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005965 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005966 c_ext++;
5967 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005968 !strcmp(sub->name, "leaf-list") ||
5969 !strcmp(sub->name, "leaf") ||
5970 !strcmp(sub->name, "list") ||
5971 !strcmp(sub->name, "choice") ||
5972 !strcmp(sub->name, "uses") ||
5973 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005974 !strcmp(sub->name, "anyxml") ||
5975 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005976 lyxml_unlink_elem(ctx, sub, 2);
5977 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005979 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005980 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005981 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02005982 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005983 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005984
Radek Krejci1a31efe2016-07-29 11:04:16 +02005985 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005986 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02005987 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02005988 c_must++;
5989
Michal Vasko38d01f72015-06-15 09:41:06 +02005990 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005991 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005992 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005993 }
5994 }
5995
5996 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5997 if (c_tpdf) {
5998 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005999 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006000 }
Radek Krejci19332802016-07-29 10:39:46 +02006001 if (c_must) {
6002 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006003 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02006004 }
Radek Krejcie534c132016-11-23 13:32:31 +01006005 if (c_ext) {
6006 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006007 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01006008 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006009
Radek Krejcie534c132016-11-23 13:32:31 +01006010 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6011 if (strcmp(sub->ns->value, LY_NSYIN)) {
6012 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006013 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 +01006014 retval->ext_size++;
6015 if (r) {
6016 goto error;
6017 }
6018 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006019 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006020 inout->must_size++;
6021 if (r) {
6022 goto error;
6023 }
6024 } else { /* typedef */
6025 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
6026 inout->tpdf_size++;
6027 if (r) {
6028 goto error;
6029 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006030 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006031 }
6032
6033 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006034 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02006035 LY_TREE_FOR_SAFE(root.child, next, sub) {
6036 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006037 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006038 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006039 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006040 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006041 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006042 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006043 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006044 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006045 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006046 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006047 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006048 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006049 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006050 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006051 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006052 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006053 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006054 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006055 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006056 goto error;
6057 }
Radek Krejci73adb602015-07-02 18:07:40 +02006058
Michal Vasko53b7da02018-02-13 15:28:42 +01006059 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006060 }
6061
Michal Vasko508a50d2016-09-07 14:50:33 +02006062 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006063 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006064 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006065 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006066 goto error;
6067 }
6068 } else {
6069 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6070 goto error;
6071 }
6072 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006073 }
6074
Michal Vasko38d01f72015-06-15 09:41:06 +02006075 return retval;
6076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006077error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006078 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006079 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006080 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006081 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006082 return NULL;
6083}
6084
Michal Vasko0d343d12015-08-24 14:57:36 +02006085/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006086static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006087read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006088 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006089{
Michal Vasko53b7da02018-02-13 15:28:42 +01006090 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006091 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006092 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006093 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006094 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006095 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006096 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006097 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006098
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006099 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006100 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006101 return NULL;
6102 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006103
Michal Vaskoc6551b32015-06-16 10:51:43 +02006104 memset(&root, 0, sizeof root);
6105
Michal Vasko0ea41032015-06-16 08:53:55 +02006106 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006107 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006108
Radek Krejci76512572015-08-04 09:47:08 +02006109 notif->nodetype = LYS_NOTIF;
6110 notif->prev = (struct lys_node *)notif;
6111 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006112
Radek Krejci07d0fb92017-01-13 14:11:05 +01006113 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006114 goto error;
6115 }
6116
Michal Vasko3e3228d2017-02-24 14:55:32 +01006117 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006118
Radek Krejcic189a952016-07-11 15:27:07 +02006119 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006120 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006121 goto error;
6122 }
6123
Michal Vasko0ea41032015-06-16 08:53:55 +02006124 /* process rpc's specific children */
6125 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006126 if (strcmp(sub->ns->value, LY_NSYIN)) {
6127 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006128 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006129 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006130 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006131
Michal Vasko0ea41032015-06-16 08:53:55 +02006132 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006133 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006134 !strcmp(sub->name, "leaf-list") ||
6135 !strcmp(sub->name, "leaf") ||
6136 !strcmp(sub->name, "list") ||
6137 !strcmp(sub->name, "choice") ||
6138 !strcmp(sub->name, "uses") ||
6139 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006140 !strcmp(sub->name, "anyxml") ||
6141 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006142 lyxml_unlink_elem(ctx, sub, 2);
6143 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006145 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006146 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006147 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006148 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006149 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006150 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006151 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006152 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006153 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006154 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006155 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006156 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006157 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006158 }
6159 }
6160
6161 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6162 if (c_tpdf) {
6163 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006164 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006165 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006166 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006167 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006168 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006169 }
Radek Krejci19332802016-07-29 10:39:46 +02006170 if (c_must) {
6171 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006172 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006173 }
Radek Krejcie534c132016-11-23 13:32:31 +01006174 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006175 /* some extensions may be already present from the substatements */
6176 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006177 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006178 retval->ext = reallocated;
6179
6180 /* init memory */
6181 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006182 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006183
Radek Krejcie534c132016-11-23 13:32:31 +01006184 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6185 if (strcmp(sub->ns->value, LY_NSYIN)) {
6186 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006187 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 +01006188 retval->ext_size++;
6189 if (r) {
6190 goto error;
6191 }
6192 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006193 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6194 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006195 if (r) {
6196 goto error;
6197 }
Radek Krejci96299152016-06-22 10:17:50 +02006198 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006199 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006200 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006201 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006202 goto error;
6203 }
Radek Krejci19332802016-07-29 10:39:46 +02006204 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006205 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006206 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006207 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006208 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006209 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006210 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006211 }
6212
6213 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006214 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006215 LY_TREE_FOR_SAFE(root.child, next, sub) {
6216 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006217 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006218 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006219 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006220 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006221 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006222 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006223 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006224 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006225 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006226 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006227 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006228 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006229 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006230 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006231 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006232 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006233 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006234 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006235 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006236 goto error;
6237 }
Radek Krejci73adb602015-07-02 18:07:40 +02006238
Michal Vasko53b7da02018-02-13 15:28:42 +01006239 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006240 }
6241
Michal Vasko508a50d2016-09-07 14:50:33 +02006242 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006243 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006244 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006245 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006246 goto error;
6247 }
6248 } else {
6249 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6250 goto error;
6251 }
6252 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006253 }
6254
Michal Vasko0ea41032015-06-16 08:53:55 +02006255 return retval;
6256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006257error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006258 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006259 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006260 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006261 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006262 return NULL;
6263}
6264
Michal Vasko0d343d12015-08-24 14:57:36 +02006265/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006266static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006267read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006268 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006269{
Michal Vasko53b7da02018-02-13 15:28:42 +01006270 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006271 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006272 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006273 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006274 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006275 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006276 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006277 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006278
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006279 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006280 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006281 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006282 return NULL;
6283 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006284 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006285 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006286 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006287 LOGVAL(ctx, LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006288 return NULL;
6289 }
6290 }
6291 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006292
Radek Krejcie0674f82015-06-15 13:58:51 +02006293 /* init */
6294 memset(&root, 0, sizeof root);
6295
Michal Vasko38d01f72015-06-15 09:41:06 +02006296 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006297 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006298
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006299 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006300 rpc->prev = (struct lys_node *)rpc;
6301 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006302
Radek Krejci07d0fb92017-01-13 14:11:05 +01006303 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006304 goto error;
6305 }
6306
Michal Vasko3e3228d2017-02-24 14:55:32 +01006307 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006308
Radek Krejcic189a952016-07-11 15:27:07 +02006309 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006310 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006311 goto error;
6312 }
6313
Michal Vasko38d01f72015-06-15 09:41:06 +02006314 /* process rpc's specific children */
6315 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006316 if (strcmp(sub->ns->value, LY_NSYIN)) {
6317 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006318 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006319 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006320 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006321 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006322 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006323 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006324 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006325 goto error;
6326 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006327 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006328 lyxml_unlink_elem(ctx, sub, 2);
6329 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006330 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006331 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006332 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006333 goto error;
6334 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006335 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006336 lyxml_unlink_elem(ctx, sub, 2);
6337 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006339 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006340 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006341 lyxml_unlink_elem(ctx, sub, 2);
6342 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006344 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006345 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006346 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006347 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006348 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006349 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006350 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006351 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006352 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006353 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006354 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006355 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006356 }
6357 }
6358
6359 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6360 if (c_tpdf) {
6361 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006362 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006363 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006364 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006365 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006366 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006367 }
Radek Krejcie534c132016-11-23 13:32:31 +01006368 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006369 /* some extensions may be already present from the substatements */
6370 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006371 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006372 retval->ext = reallocated;
6373
6374 /* init memory */
6375 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006376 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006377
Radek Krejcie534c132016-11-23 13:32:31 +01006378 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6379 if (strcmp(sub->ns->value, LY_NSYIN)) {
6380 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006381 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 +01006382 retval->ext_size++;
6383 if (r) {
6384 goto error;
6385 }
6386 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006387 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6388 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006389 if (r) {
6390 goto error;
6391 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006392 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006393 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006394 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006395 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006396 goto error;
6397 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006398 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006399 }
6400
6401 /* last part - process data nodes */
6402 LY_TREE_FOR_SAFE(root.child, next, sub) {
6403 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006404 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006405 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006406 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006407 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006408 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006409 goto error;
6410 }
Radek Krejci73adb602015-07-02 18:07:40 +02006411
Michal Vasko53b7da02018-02-13 15:28:42 +01006412 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006413 }
6414
Michal Vasko38d01f72015-06-15 09:41:06 +02006415 return retval;
6416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006417error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006418 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006419 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006420 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006421 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006422 return NULL;
6423}
6424
Michal Vasko0d343d12015-08-24 14:57:36 +02006425/* logs directly
6426 *
Radek Krejci74705112015-06-05 10:25:44 +02006427 * resolve - referenced grouping should be bounded to the namespace (resolved)
6428 * only when uses does not appear in grouping. In a case of grouping's uses,
6429 * we just get information but we do not apply augment or refine to it.
6430 */
Radek Krejci76512572015-08-04 09:47:08 +02006431static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006432read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6433 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006434{
Michal Vasko53b7da02018-02-13 15:28:42 +01006435 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006436 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006437 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006438 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006439 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006440 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006441 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006442 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006444 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006445 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006446
Radek Krejci76512572015-08-04 09:47:08 +02006447 uses->nodetype = LYS_USES;
6448 uses->prev = (struct lys_node *)uses;
6449 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006450
Michal Vasko53b7da02018-02-13 15:28:42 +01006451 GETVAL(ctx, value, yin, "name");
6452 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006453
Radek Krejci07d0fb92017-01-13 14:11:05 +01006454 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006455 goto error;
6456 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006457
Michal Vasko3e3228d2017-02-24 14:55:32 +01006458 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006459
Radek Krejcic189a952016-07-11 15:27:07 +02006460 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006461 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006462 goto error;
6463 }
6464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006465 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006466 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006467 if (strcmp(sub->ns->value, LY_NSYIN)) {
6468 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006469 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006470 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006471 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006472 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006473 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006474 c_ref++;
6475 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006476 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006477 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006478 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006479 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006480 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006481 } else if (!strcmp(sub->name, "when")) {
6482 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006483 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006484 goto error;
6485 }
6486
Radek Krejci5323b492017-01-16 15:40:11 +01006487 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006488 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006489 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006490 goto error;
6491 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006492 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006493 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006494 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006495 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006496 }
6497 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006499 /* process properties with cardinality 0..n */
6500 if (c_ref) {
6501 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006502 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006503 }
6504 if (c_aug) {
6505 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006506 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006507 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006508 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006509 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006510 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006511 }
Radek Krejcie534c132016-11-23 13:32:31 +01006512 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006513 /* some extensions may be already present from the substatements */
6514 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006515 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006516 retval->ext = reallocated;
6517
6518 /* init memory */
6519 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006520 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006521
Radek Krejcie534c132016-11-23 13:32:31 +01006522 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6523 if (strcmp(sub->ns->value, LY_NSYIN)) {
6524 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006525 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 +01006526 retval->ext_size++;
6527 if (r) {
6528 goto error;
6529 }
6530 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006531 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006532 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006533 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006534 goto error;
6535 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006536 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006537 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006538 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006539 if (r) {
6540 goto error;
6541 }
6542 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006543 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006544 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006545 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006546 goto error;
6547 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006548 }
6549 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006550
Radek Krejci48464ed2016-03-17 15:44:09 +01006551 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006552 goto error;
6553 }
Radek Krejci74705112015-06-05 10:25:44 +02006554
Michal Vasko508a50d2016-09-07 14:50:33 +02006555 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006556 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006557 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006558 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006559 goto error;
6560 }
6561 } else {
6562 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6563 goto error;
6564 }
6565 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006566 }
6567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006568 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006569
6570error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006571 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006572 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006573}
6574
Michal Vasko0d343d12015-08-24 14:57:36 +02006575/* logs directly
6576 *
6577 * common code for yin_read_module() and yin_read_submodule()
6578 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006579static int
Radek Krejcic071c542016-01-27 14:57:51 +01006580read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6581 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006582{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006583 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006584 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006585 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006586 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006587 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006588 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006589 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006590 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6591 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6592 int substmt_group;
6593 /* just remember last substatement for logging */
6594 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006595 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006596 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;
6597 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006598 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006599
Radek Krejcic071c542016-01-27 14:57:51 +01006600 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006601 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006603 /* init */
6604 memset(&root, 0, sizeof root);
6605 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006606 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006607 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006608 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006610 /*
6611 * in the first run, we process elements with cardinality of 1 or 0..1 and
6612 * count elements with cardinality 0..n. Data elements (choices, containers,
6613 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6614 * need have all top-level and groupings already prepared at that time. In
6615 * the middle loop, we process other elements with carinality of 0..n since
6616 * we need to allocate arrays to store them.
6617 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006618 substmt_group = 0;
6619 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006620 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006621 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006622 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006623 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006624 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006625 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006626 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006627 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006628 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006629 lyxml_unlink_elem(ctx, child, 2);
6630 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006631 c_extinst++;
6632 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006633 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006634 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6635 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006636 child->name, substmt_prev);
6637 goto error;
6638 }
6639
PavolVican9e81c6a2017-02-09 13:09:07 +01006640 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006641 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006642 goto error;
6643 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006644 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006645 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006646
Radek Krejci8d6b7422017-02-03 14:42:13 +01006647 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006648 goto error;
6649 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006650 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006651
6652 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006653 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006654 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006655 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6656 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006657 child->name, substmt_prev);
6658 goto error;
6659 }
6660
PavolVican9e81c6a2017-02-09 13:09:07 +01006661 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006662 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006663 goto error;
6664 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006665 GETVAL(ctx, value, child, "value");
6666 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006667 goto error;
6668 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006669 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006670
Radek Krejci8d6b7422017-02-03 14:42:13 +01006671 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006672 goto error;
6673 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006674 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006675
6676 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006677 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006678 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006679 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6680 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006681 child->name, substmt_prev);
6682 goto error;
6683 }
6684
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006685 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006686 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006687 goto error;
6688 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006689 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006690 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006691 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006692 goto error;
6693 }
Radek Krejcif3886932015-06-04 17:36:06 +02006694
Radek Krejci8d6b7422017-02-03 14:42:13 +01006695 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006696 goto error;
6697 }
6698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006699 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006700 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006701 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006702 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006703 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006704 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006705 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006706 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006707 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006708 goto error;
6709 }
6710 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006711 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006712 /* check here differs from a generic prefix check, since this prefix
6713 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006714 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006715 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006716 goto error;
6717 }
Radek Krejcic071c542016-01-27 14:57:51 +01006718 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006719
Radek Krejci8d6b7422017-02-03 14:42:13 +01006720 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 +01006721 goto error;
6722 }
6723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006724 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006725 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006726
Michal Vasko5de8a022017-02-08 10:57:26 +01006727 substmt_prev = "belongs-to";
6728
Radek Krejcieb00f512015-07-01 16:44:58 +02006729 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006730 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006731 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006732 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6733 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006734 child->name, substmt_prev);
6735 goto error;
6736 }
6737 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006738 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006739 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006740 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006741
6742 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006743 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006744 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006745 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6746 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006747 child->name, substmt_prev);
6748 goto error;
6749 }
6750 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006751 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006752 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006753 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006754
PavolVican9e81c6a2017-02-09 13:09:07 +01006755 lyxml_unlink_elem(ctx, child, 2);
6756 lyxml_add_child(ctx, &revs, child);
6757
Michal Vasko5de8a022017-02-08 10:57:26 +01006758 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006759 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006760 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006761 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006762 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006763 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006764
6765 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006766 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006767 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006768 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006769 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006770 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006771
6772 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006773 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006774 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006775 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6776 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006777 child->name, substmt_prev);
6778 goto error;
6779 }
6780 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006781 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006782 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006783 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006784
6785 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006786 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006787 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006788 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006789 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006790 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006791 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006792 lyxml_unlink_elem(ctx, child, 2);
6793 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006794
Michal Vasko5de8a022017-02-08 10:57:26 +01006795 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006796 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006797 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006798 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006799 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006800 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006801
Michal Vasko5de8a022017-02-08 10:57:26 +01006802 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006804 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006805 } else if (!strcmp(child->name, "container") ||
6806 !strcmp(child->name, "leaf-list") ||
6807 !strcmp(child->name, "leaf") ||
6808 !strcmp(child->name, "list") ||
6809 !strcmp(child->name, "choice") ||
6810 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006811 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006812 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006813 !strcmp(child->name, "rpc") ||
6814 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006815 substmt_group = 4;
6816
Radek Krejcic071c542016-01-27 14:57:51 +01006817 lyxml_unlink_elem(ctx, child, 2);
6818 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006819
Michal Vasko5de8a022017-02-08 10:57:26 +01006820 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006821 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006822 substmt_group = 4;
6823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006824 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006825 lyxml_unlink_elem(ctx, child, 2);
6826 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006827
Michal Vasko5de8a022017-02-08 10:57:26 +01006828 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006829 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006830 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006831 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006832 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6833 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006834 child->name, substmt_prev);
6835 goto error;
6836 }
6837 substmt_group = 2;
6838
Radek Krejcic071c542016-01-27 14:57:51 +01006839 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006840 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006841 goto error;
6842 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006843 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006844 goto error;
6845 }
Radek Krejcic071c542016-01-27 14:57:51 +01006846 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006847 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006848 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006849 goto error;
6850 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006851
6852 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006853 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006854 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006855 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6856 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006857 child->name, substmt_prev);
6858 goto error;
6859 }
6860 substmt_group = 2;
6861
Radek Krejcic071c542016-01-27 14:57:51 +01006862 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006863 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006864 goto error;
6865 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006866 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006867 goto error;
6868 }
Radek Krejcic071c542016-01-27 14:57:51 +01006869 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006870 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006871 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006872 goto error;
6873 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006874
6875 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006876 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006877 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006878 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6879 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006880 child->name, substmt_prev);
6881 goto error;
6882 }
6883 substmt_group = 2;
6884
Radek Krejcic071c542016-01-27 14:57:51 +01006885 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006886 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006887 goto error;
6888 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006889 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006890 goto error;
6891 }
Radek Krejcic071c542016-01-27 14:57:51 +01006892 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006893 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006894 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006895 goto error;
6896 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006897
6898 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006899 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006900 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006901 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6902 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006903 child->name, substmt_prev);
6904 goto error;
6905 }
6906 substmt_group = 2;
6907
Radek Krejcic071c542016-01-27 14:57:51 +01006908 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006909 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006910 goto error;
6911 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006912 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006913 goto error;
6914 }
Radek Krejcic071c542016-01-27 14:57:51 +01006915 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006916 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006917 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006918 goto error;
6919 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006920
6921 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006922 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006923 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006924 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6925 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006926 child->name, substmt_prev);
6927 goto error;
6928 }
6929
Radek Krejcic071c542016-01-27 14:57:51 +01006930 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006931 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006932 goto error;
6933 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006934 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006935 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006936 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006937 goto error;
6938 }
Radek Krejcic071c542016-01-27 14:57:51 +01006939 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006940 if (!strcmp(value, "1")) {
6941 if (submodule) {
6942 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006943 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006944 goto error;
6945 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006946 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006947 } else {
6948 module->version = 1;
6949 }
6950 } else {
6951 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006952 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006953 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006954 goto error;
6955 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006956 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006957 } else {
6958 module->version = 2;
6959 }
6960 }
6961
Radek Krejci8d6b7422017-02-03 14:42:13 +01006962 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006963 goto error;
6964 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006965 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006966
Michal Vasko5de8a022017-02-08 10:57:26 +01006967 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006968 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006969 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006970 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006971 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006972 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006973
Michal Vasko5de8a022017-02-08 10:57:26 +01006974 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006975 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006976 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006977 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006978 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006979 c_dev++;
6980
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006981 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006982 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006983 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006984 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006985 }
6986 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006987
Radek Krejcic071c542016-01-27 14:57:51 +01006988 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006989 if (submodule) {
6990 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006991 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006992 goto error;
6993 }
6994 if (!version_flag) {
6995 /* check version compatibility with the main module */
6996 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006997 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006998 goto error;
6999 }
7000 }
7001 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01007002 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007003 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007004 goto error;
7005 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007006 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007007 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007008 goto error;
7009 }
7010 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02007011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007012 /* allocate arrays for elements with cardinality of 0..n */
7013 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007014 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01007015 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007016 }
7017 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007018 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01007019 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007020 }
7021 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01007022 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01007023 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007024 }
7025 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01007026 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01007027 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007028 }
7029 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007030 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01007031 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007032 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007033 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01007034 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01007035 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007036 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02007037 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01007038 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007039 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007040 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007041 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007042 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007043 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007044 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007045 if (c_ext) {
7046 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007047 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007048 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007049
PavolVican9e81c6a2017-02-09 13:09:07 +01007050 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7051 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007052 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7053 trg->rev_size++;
7054 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007055 goto error;
7056 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007057
Radek Krejci7417a082017-02-16 11:07:59 +01007058 /* check uniqueness of the revision date - not required by RFC */
7059 for (i = 0; i < (trg->rev_size - 1); i++) {
7060 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007061 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007062 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007063 }
7064 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007065
7066 lyxml_free(ctx, child);
7067 }
7068
7069 /* check the module with respect to the context now */
7070 if (!submodule) {
7071 switch (lyp_ctx_check_module(module)) {
7072 case -1:
7073 goto error;
7074 case 0:
7075 break;
7076 case 1:
7077 /* it's already there */
7078 ret = 1;
7079 goto error;
7080 }
7081 }
7082
PavolVican92f23622017-12-12 13:35:56 +01007083 /* check first definition of extensions */
7084 if (c_ext) {
7085 LY_TREE_FOR_SAFE(yin->child, next, child) {
7086 if (!strcmp(child->name, "extension")) {
7087 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7088 trg->extensions_size++;
7089 if (r) {
7090 goto error;
7091 }
7092
7093 }
7094 }
7095 }
7096
PavolVican9e81c6a2017-02-09 13:09:07 +01007097 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007098 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007099 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007100 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007101 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007102 if (r) {
7103 goto error;
7104 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007105
Radek Krejci1d82ef62015-08-07 14:44:40 +02007106 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007107 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7108 trg->inc_size++;
7109 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007110 goto error;
7111 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007112
Radek Krejci1d82ef62015-08-07 14:44:40 +02007113 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007114 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7115 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007116 if (r) {
7117 goto error;
7118 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007119
Radek Krejci1d82ef62015-08-07 14:44:40 +02007120 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007121 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7122 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007123 if (r) {
7124 goto error;
7125 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007126
Radek Krejci1d82ef62015-08-07 14:44:40 +02007127 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007128 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7129 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007130 if (r) {
7131 goto error;
7132 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007133
Radek Krejci1d82ef62015-08-07 14:44:40 +02007134 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko0f437062018-06-08 15:52:39 +02007135 /* must be implemented in this case */
7136 trg->implemented = 1;
7137
Radek Krejcic071c542016-01-27 14:57:51 +01007138 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7139 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007140 if (r) {
7141 goto error;
7142 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007143 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007144 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007145
Radek Krejcie534c132016-11-23 13:32:31 +01007146 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007147 if (c_extinst) {
7148 /* some extensions may be already present from the substatements */
7149 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007150 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007151 trg->ext = reallocated;
7152
7153 /* init memory */
7154 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7155
7156 LY_TREE_FOR_SAFE(exts.child, next, child) {
7157 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7158 trg->ext_size++;
7159 if (r) {
7160 goto error;
7161 }
7162 }
Radek Krejcie534c132016-11-23 13:32:31 +01007163 }
7164
Radek Krejcif5be10f2015-06-16 13:29:36 +02007165 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007166 * refer to them. Submodule's data nodes are stored in the
7167 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007168 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007169 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007170 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007171 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007172 goto error;
7173 }
Radek Krejci74705112015-06-05 10:25:44 +02007174
Michal Vasko345da0a2015-12-02 10:35:55 +01007175 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007176 }
Radek Krejci74705112015-06-05 10:25:44 +02007177
Radek Krejcif5be10f2015-06-16 13:29:36 +02007178 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007179 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007180
Radek Krejci1d82ef62015-08-07 14:44:40 +02007181 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007182 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007183 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007184 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007185 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007186 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007187 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007188 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007189 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007190 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007191 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007192 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007193 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007194 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007195 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007196 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007197 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007198 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007199 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007200 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007201 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007202 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007203 goto error;
7204 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007205
Michal Vasko345da0a2015-12-02 10:35:55 +01007206 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007207 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007208
Michal Vasko2f7925f2015-10-21 15:06:56 +02007209 /* ... and finally augments (last, so we can augment our data, for instance) */
7210 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007211 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007212 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007213
Michal Vasko2f7925f2015-10-21 15:06:56 +02007214 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007215 goto error;
7216 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007217 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007218 }
7219
PavolVican9e81c6a2017-02-09 13:09:07 +01007220 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007221
7222error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007223 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007224 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007225 }
7226 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007227 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007228 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007229 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007230 lyxml_free(ctx, augs.child);
7231 }
7232 while (revs.child) {
7233 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007234 }
Radek Krejcie534c132016-11-23 13:32:31 +01007235 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007236 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007237 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007238
PavolVican9e81c6a2017-02-09 13:09:07 +01007239 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007240}
7241
Michal Vasko0d343d12015-08-24 14:57:36 +02007242/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007243struct lys_submodule *
7244yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007245{
Michal Vasko53b7da02018-02-13 15:28:42 +01007246 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007247 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007248 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007249 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007250
Michal Vasko53b7da02018-02-13 15:28:42 +01007251 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007252 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007253 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007254 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007256 /* check root element */
7257 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007258 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007259 goto error;
7260 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007261
Michal Vasko53b7da02018-02-13 15:28:42 +01007262 GETVAL(ctx, value, yin, "name");
7263 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007264 goto error;
7265 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007266
Michal Vasko5a721fd2016-02-16 12:16:48 +01007267 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007268 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007269
Michal Vasko53b7da02018-02-13 15:28:42 +01007270 submodule->ctx = ctx;
7271 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007272 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007273 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007274 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007275
Radek Krejci9e757e02017-03-08 17:18:09 +01007276 /* add into the list of processed modules */
7277 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7278 goto error;
7279 }
7280
Michal Vasko5a721fd2016-02-16 12:16:48 +01007281 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007282 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007283 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007284 goto error;
7285 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007286
Radek Krejci33fc4772017-01-26 16:00:35 +01007287 lyp_sort_revisions((struct lys_module *)submodule);
7288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007289 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007290 lyxml_free(ctx, yin);
7291 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007292
Michal Vasko5a721fd2016-02-16 12:16:48 +01007293 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007294 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007295
7296error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007297 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007298 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007299 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007300 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007301 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007302 }
7303
Michal Vasko53b7da02018-02-13 15:28:42 +01007304 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007305
Michal Vaskoa9728122018-01-16 14:00:13 +01007306 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007307 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007308 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7309 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007310 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007311 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007312}
7313
Michal Vasko0d343d12015-08-24 14:57:36 +02007314/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007315struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007316yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007317{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007318 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007319 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007320 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007321 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007322
Radek Krejcic071c542016-01-27 14:57:51 +01007323 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007324 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007326 /* check root element */
7327 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007328 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007329 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007330 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007331 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007332 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007333 goto error;
7334 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007335
Michal Vasko53b7da02018-02-13 15:28:42 +01007336 GETVAL(ctx, value, yin, "name");
7337 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007338 goto error;
7339 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007341 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007342 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007344 module->ctx = ctx;
7345 module->name = lydict_insert(ctx, value, strlen(value));
7346 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007347 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007348
Radek Krejci9e757e02017-03-08 17:18:09 +01007349 /* add into the list of processed modules */
7350 if (lyp_check_circmod_add(module)) {
7351 goto error;
7352 }
7353
Michal Vasko9f258e42016-02-11 11:36:27 +01007354 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007355 ret = read_sub_module(module, NULL, yin, unres);
7356 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007357 goto error;
7358 }
7359
PavolVican9e81c6a2017-02-09 13:09:07 +01007360 if (ret == 1) {
7361 assert(!unres->count);
7362 } else {
Michal Vasko0f437062018-06-08 15:52:39 +02007363 /* make this module implemented if was not from start */
7364 if (!implement && module->implemented && (unres_schema_add_node(module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1)) {
7365 goto error;
7366 }
7367
PavolVican9e81c6a2017-02-09 13:09:07 +01007368 /* resolve rest of unres items */
7369 if (unres->count && resolve_unres_schema(module, unres)) {
7370 goto error;
7371 }
7372
7373 /* check correctness of includes */
7374 if (lyp_check_include_missing(module)) {
7375 goto error;
7376 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007377 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007378
Radek Krejci95f22ae2017-01-20 14:25:53 +01007379 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007380
7381 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7382 goto error;
7383 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007384
Radek Krejciff4874d2016-03-07 12:30:50 +01007385 if (revision) {
7386 /* check revision of the parsed model */
7387 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007388 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7389 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007390 goto error;
7391 }
7392 }
7393
PavolVican9e81c6a2017-02-09 13:09:07 +01007394 /* add into context if not already there */
7395 if (!ret) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007396 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007397 goto error;
7398 }
Michal Vasko10681e82018-01-16 14:54:16 +01007399
7400 /* remove our submodules from the parsed submodules list */
7401 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007402 } else {
7403 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007404 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007405
7406 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007407 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007408 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007409 }
7410
Michal Vasko44ab1462017-05-18 13:18:36 +02007411 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007412 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007413 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7414 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007415 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007416
7417error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007418 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007419 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007420
7421 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007422 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7423 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007424 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007425 return NULL;
7426 }
7427
Michal Vasko53b7da02018-02-13 15:28:42 +01007428 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007429
Radek Krejci9e757e02017-03-08 17:18:09 +01007430 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007431 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007432 lyp_del_includedup(module, 1);
7433 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007434 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007435}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007436
Radek Krejci37f9ba32017-02-10 16:50:35 +01007437/* logs directly */
7438struct lys_module *
7439yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7440{
7441 struct lyxml_elem *yin;
7442 struct lys_module *result;
7443
Radek Krejcie1bacd72017-03-01 13:18:46 +01007444 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007445 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007446 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007447 return NULL;
7448 }
7449
7450 result = yin_read_module_(ctx, yin, revision, implement);
7451
7452 lyxml_free(ctx, yin);
7453
7454 return result;
7455}
7456
Radek Krejcic1885952017-02-07 09:37:51 +01007457static int
7458yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007459 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007460 const char *true_val, const char *false_val, struct unres_schema *unres)
7461{
7462 uint8_t *val;
7463 const char *str;
7464 struct lyext_substmt *info;
7465
7466 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7467 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007468 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007469 return EXIT_FAILURE;
7470 }
7471 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007472 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007473 return EXIT_FAILURE;
7474 }
7475
Radek Krejcidb35f172017-02-27 11:03:01 +01007476 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007477 return EXIT_FAILURE;
7478 }
7479
7480 str = lyxml_get_attr(node, "value", NULL);
7481 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007482 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007483 } else if (true_val && !strcmp(true_val, str)) {
7484 /* true value */
7485 *val = 1;
7486 } else if (false_val && !strcmp(false_val, str)) {
7487 /* false value */
7488 *val = 2;
7489 } else {
7490 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007491 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007492 return EXIT_FAILURE;
7493 }
7494
7495 return EXIT_SUCCESS;
7496}
7497
Radek Krejci8d6b7422017-02-03 14:42:13 +01007498/*
7499 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7500 * argname - name of the element/attribute where the value is stored
7501 */
7502static int
7503yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007504 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007505 int argelem, const char *argname, struct unres_schema *unres)
7506{
7507 int c;
PavolVican99c70722017-02-18 17:25:52 +01007508 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007509 void *reallocated;
7510 struct lyext_substmt *info;
7511
7512 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7513 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007514 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007515 return EXIT_FAILURE;
7516 }
7517 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007518 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007519 return EXIT_FAILURE;
7520 }
7521
7522 c = 0;
7523 if (info->cardinality >= LY_STMT_CARD_SOME) {
7524 /* there can be multiple instances, str is actually const char *** */
7525 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007526 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007527 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007528 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007529 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007530 if (stmt == LY_STMT_BELONGSTO) {
7531 /* allocate another array for the belongs-to's prefixes */
7532 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007533 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007534 } else if (stmt == LY_STMT_ARGUMENT) {
7535 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007536 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007537 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007538 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007539 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007540 /* get the index in the array to add new item */
7541 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007542 }
Radek Krejci56c80412017-02-09 10:44:16 +01007543 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007544 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007545 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007546 return EXIT_FAILURE;
7547 }
7548
7549 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007550 str[c] = read_yin_subnode(mod->ctx, node, argname);
7551 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007552 return EXIT_FAILURE;
7553 }
Radek Krejci56c80412017-02-09 10:44:16 +01007554 } else {
7555 str[c] = lyxml_get_attr(node, argname, NULL);
7556 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007557 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007558 return EXIT_FAILURE;
7559 } else {
7560 str[c] = lydict_insert(mod->ctx, str[c], 0);
7561 }
7562
7563 if (stmt == LY_STMT_BELONGSTO) {
7564 /* get the belongs-to's mandatory prefix substatement */
7565 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007566 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007567 return EXIT_FAILURE;
7568 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007569 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007570 return EXIT_FAILURE;
7571 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007572 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007573 return EXIT_FAILURE;
7574 }
7575 /* and now finally get the value */
7576 if (p) {
7577 str = p[1];
7578 } else {
7579 str++;
7580 }
7581 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7582 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007583 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007584 return EXIT_FAILURE;
7585 }
7586 str[c] = lydict_insert(mod->ctx, str[c], 0);
7587
PavolVican6d400872017-03-01 15:19:18 +01007588 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 +01007589 return EXIT_FAILURE;
7590 }
PavolVican99c70722017-02-18 17:25:52 +01007591 } else if (stmt == LY_STMT_ARGUMENT) {
7592 str = (p) ? p[1] : str + 1;
7593 if (!node->child) {
7594 /* default value of yin element */
7595 ((uint8_t *)str)[c] = 2;
7596 } else {
7597 /* get optional yin-element substatement */
7598 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007599 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007600 return EXIT_FAILURE;
7601 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007602 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007603 return EXIT_FAILURE;
7604 } else {
7605 /* and now finally get the value */
7606 value = lyxml_get_attr(node->child, "value", NULL);
7607 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007608 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007609 return EXIT_FAILURE;
7610 }
7611 if (ly_strequal(value, "true", 0)) {
7612 ((uint8_t *)str)[c] = 1;
7613 } else if (ly_strequal(value, "false", 0)) {
7614 ((uint8_t *)str)[c] = 2;
7615 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007616 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007617 return EXIT_FAILURE;
7618 }
7619
7620 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7621 return EXIT_FAILURE;
7622 }
7623 }
7624 }
Radek Krejci56c80412017-02-09 10:44:16 +01007625 }
7626 }
7627 if (p) {
7628 /* enlarge the array(s) */
7629 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7630 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007631 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007632 lydict_remove(mod->ctx, p[0][c]);
7633 p[0][c] = NULL;
7634 return EXIT_FAILURE;
7635 }
7636 p[0] = reallocated;
7637 p[0][c + 1] = NULL;
7638
7639 if (stmt == LY_STMT_BELONGSTO) {
7640 /* enlarge the second belongs-to's array with prefixes */
7641 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7642 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007643 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007644 lydict_remove(mod->ctx, p[1][c]);
7645 p[1][c] = NULL;
7646 return EXIT_FAILURE;
7647 }
7648 p[1] = reallocated;
7649 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007650 } else if (stmt == LY_STMT_ARGUMENT){
7651 /* enlarge the second argument's array with yin element */
7652 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7653 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007654 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007655 ((uint8_t *)p[1])[c] = 0;
7656 return EXIT_FAILURE;
7657 }
7658 p[1] = reallocated;
7659 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007660 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007661 }
7662
7663 return EXIT_SUCCESS;
7664}
7665
7666static void *
7667yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7668 uint16_t mask)
7669{
7670 void *data;
7671 struct lyext_substmt *info;
7672
7673 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7674 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007675 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007676 return NULL;
7677 }
7678 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007679 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007680 return NULL;
7681 }
7682
7683 return data;
7684}
7685
Radek Krejcic1885952017-02-07 09:37:51 +01007686static int
7687yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007688 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007689 const char *val1_str, const char *val2_str, uint16_t mask,
7690 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7691{
7692 uint16_t *val;
7693 const char *str;
7694
7695 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7696 if (!val) {
7697 return EXIT_FAILURE;
7698 }
7699
7700 str = lyxml_get_attr(node, "value", NULL);
7701 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007702 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007703 } else if (!strcmp(val1_str, str)) {
7704 *val = *val | val1;
7705 } else if (!strcmp(val2_str, str)) {
7706 *val = *val | val2;
7707 } else {
7708 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007709 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007710 return EXIT_FAILURE;
7711 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007712 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007713 return EXIT_FAILURE;
7714 }
7715 return EXIT_SUCCESS;
7716}
7717
Radek Krejcif95b6292017-02-13 15:57:37 +01007718static struct lys_node **
7719yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7720{
7721 struct lyext_substmt *info;
7722 struct lys_node **snode, *siter;
7723
7724 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7725 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007726 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007727 return NULL;
7728 }
7729 if (info->cardinality < LY_STMT_CARD_SOME) {
7730 LY_TREE_FOR(*snode, siter) {
7731 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007732 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007733 return NULL;
7734 }
7735 }
7736 }
7737
7738 return snode;
7739}
7740
Radek Krejci8d6b7422017-02-03 14:42:13 +01007741static void **
7742yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7743{
7744 int c;
7745 void **data, ***p = NULL;
7746 void *reallocated;
7747 struct lyext_substmt *info;
7748
7749 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7750 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007751 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007752 return NULL;
7753 }
7754 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007755 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007756 return NULL;
7757 }
7758
7759 c = 0;
7760 if (info->cardinality >= LY_STMT_CARD_SOME) {
7761 /* there can be multiple instances, so instead of pointer to array,
7762 * we have in data pointer to pointer to array */
7763 p = (void ***)data;
7764 data = *p;
7765 if (!data) {
7766 /* allocate initial array */
7767 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007768 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007769 } else {
7770 for (c = 0; *data; data++, c++);
7771 }
7772 }
7773
7774 if (p) {
7775 /* enlarge the array */
7776 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007777 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007778 *p = reallocated;
7779 data = *p;
7780 data[c + 1] = NULL;
7781 }
7782
7783 return &data[c];
7784}
7785
7786int
7787lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7788 struct unres_schema *unres)
7789{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007790 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007791 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007792 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007793 const char *value, *name;
7794 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007795 struct lyext_substmt *info;
7796 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007797 long long int ll;
7798 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007799 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007800
Radek Krejcia8d111f2017-05-31 13:57:37 +02007801#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7802 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007803 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007804 (**(TYPE **)TO) = (TYPE)FROM;
7805
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007806#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007807 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7808 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007809 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007810 goto error; \
7811 } \
7812 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007813 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007814 goto error; \
7815 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007816 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007817 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7818 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007819 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007820 if (!(*pp)) { \
7821 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007822 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007823 } else { \
7824 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7825 } \
7826 p = &(*(TYPE**)pp)[i]; \
7827 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007828#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007829 if (pp) { \
7830 /* enlarge the array */ \
7831 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007832 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007833 *pp = reallocated; \
7834 (*(TYPE**)pp)[i + 1] = 0; \
7835 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007836#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7837 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7838 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007839 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007840#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7841 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007842 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007843 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007844 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007845 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7846 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7847 goto error; \
7848 } \
7849 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007850
Radek Krejci8d6b7422017-02-03 14:42:13 +01007851 LY_TREE_FOR_SAFE(yin->child, next, node) {
7852 if (!node->ns) {
7853 /* garbage */
7854 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7855 /* we have the extension's argument */
7856 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007857 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007858 goto error;
7859 }
7860 ext->arg_value = node->content;
7861 node->content = NULL;
7862 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7863 /* extension */
7864 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7865 goto error;
7866 }
7867 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007868 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007869 goto error;
7870 }
7871 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007872 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007873 goto error;
7874 }
7875 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007876 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007877 goto error;
7878 }
7879 } else if (!strcmp(node->name, "type")) {
7880 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7881 if (!type) {
7882 goto error;
7883 }
7884 /* allocate type structure */
7885 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007886 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007887
7888 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007889 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007890 (*type)->der = (struct lys_tpdf *)node;
7891 (*type)->parent = (struct lys_tpdf *)ext;
7892
7893 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7894 (*type)->der = NULL;
7895 goto error;
7896 }
7897 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007898 } else if (!strcmp(node->name, "typedef")) {
7899 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7900 if (!pp) {
7901 goto error;
7902 }
7903 /* allocate typedef structure */
7904 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007905 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007906
7907 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7908 goto error;
7909 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007910 } else if (!strcmp(node->name, "if-feature")) {
7911 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7912 if (!pp) {
7913 goto error;
7914 }
7915 /* allocate iffeature structure */
7916 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007917 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007918
7919 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7920 goto error;
7921 }
7922 } else if (!strcmp(node->name, "status")) {
7923 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7924 if (!p) {
7925 goto error;
7926 }
7927
Michal Vasko53b7da02018-02-13 15:28:42 +01007928 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007929 if (!strcmp(value, "current")) {
7930 *(uint16_t*)p |= LYS_STATUS_CURR;
7931 } else if (!strcmp(value, "deprecated")) {
7932 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7933 } else if (!strcmp(value, "obsolete")) {
7934 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7935 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007936 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007937 goto error;
7938 }
7939
7940 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7941 goto error;
7942 }
Radek Krejcic1885952017-02-07 09:37:51 +01007943 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007944 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007945 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007946 goto error;
7947 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007948 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007949 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007950 goto error;
7951 }
7952 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007953 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007954 goto error;
7955 }
Radek Krejcic1885952017-02-07 09:37:51 +01007956 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007957 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007958 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7959 goto error;
7960 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007961 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007962 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007963 goto error;
7964 }
7965 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007966 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007967 goto error;
7968 }
7969 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007970 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007971 goto error;
7972 }
7973 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007974 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007975 goto error;
7976 }
7977 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007978 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007979 goto error;
7980 }
7981 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007982 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007983 goto error;
7984 }
7985 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007986 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007987 goto error;
7988 }
7989 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007990 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007991 goto error;
7992 }
Radek Krejcic1885952017-02-07 09:37:51 +01007993 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007994 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7995 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007996 goto error;
7997 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007998 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007999 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008000 goto error;
8001 }
8002 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008003 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008004 goto error;
8005 }
8006 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008007 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008008 goto error;
8009 }
8010 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008011 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008012 goto error;
8013 }
Radek Krejcic1885952017-02-07 09:37:51 +01008014 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008015 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008016 goto error;
8017 }
8018 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008019 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008020 goto error;
8021 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008022 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008023 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008024
Michal Vasko53b7da02018-02-13 15:28:42 +01008025 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008026 v = strtol(value, NULL, 10);
8027
8028 /* range check */
8029 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008030 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008031 goto error;
8032 }
8033
8034 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
8035 goto error;
8036 }
8037
8038 /* store the value */
8039 (*(uint8_t *)p) = (uint8_t)v;
8040
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008041 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008042 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008043 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008044
Michal Vasko53b7da02018-02-13 15:28:42 +01008045 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008046 while (isspace(value[0])) {
8047 value++;
8048 }
8049
8050 if (!strcmp(value, "unbounded")) {
8051 u = 0;
8052 } else {
8053 /* convert it to uint32_t */
8054 errno = 0; endptr = NULL;
8055 u = strtoul(value, &endptr, 10);
8056 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008057 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008058 goto error;
8059 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008060 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008061
8062 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8063 goto error;
8064 }
8065
8066 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008067 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008068
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008069 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008070 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008071 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008072
Michal Vasko53b7da02018-02-13 15:28:42 +01008073 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008074 while (isspace(value[0])) {
8075 value++;
8076 }
8077
8078 /* convert it to uint32_t */
8079 errno = 0;
8080 endptr = NULL;
8081 u = strtoul(value, &endptr, 10);
8082 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008083 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008084 goto error;
8085 }
8086
8087 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8088 goto error;
8089 }
8090
8091 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008092 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008093
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008094 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008095 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008096 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8097
Michal Vasko53b7da02018-02-13 15:28:42 +01008098 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008099 while (isspace(value[0])) {
8100 value++;
8101 }
8102
8103 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008104 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008105
8106 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008107 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008108 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008109 goto error;
8110 }
8111
8112 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8113 goto error;
8114 }
8115
8116 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008117 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008118
8119 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008120 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008121 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008122
Michal Vasko53b7da02018-02-13 15:28:42 +01008123 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008124 ll = strtoll(value, NULL, 10);
8125
8126 /* range check */
8127 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008128 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008129 goto error;
8130 }
8131
8132 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8133 goto error;
8134 }
8135
8136 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008137 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008138
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008139 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008140 } else if (!strcmp(node->name, "module")) {
8141 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8142 if (!pp) {
8143 goto error;
8144 }
8145
8146 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8147 if (!(*pp)) {
8148 goto error;
8149 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008150 } else if (!strcmp(node->name, "when")) {
8151 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8152
8153 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8154 if (!*(struct lys_when**)p) {
8155 goto error;
8156 }
8157
8158 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008159 } else if (!strcmp(node->name, "revision")) {
8160 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8161
8162 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008163 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008164 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8165 goto error;
8166 }
8167
8168 /* check uniqueness of the revision dates - not required by RFC */
8169 if (pp) {
8170 for (j = 0; j < i; j++) {
8171 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008172 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008173 }
8174 }
8175 }
8176
8177 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008178 } else if (!strcmp(node->name, "unique")) {
8179 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8180
8181 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008182 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008183 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8184 goto error;
8185 }
8186
8187 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8188 goto error;
8189 }
8190 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008191 } else if (!strcmp(node->name, "action")) {
8192 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8193 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008194 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008195 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008196 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008197 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008198 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008199 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008200 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008201 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008202 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008203 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008204 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008205 } else if (!strcmp(node->name, "output")) {
8206 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8207 } else if (!strcmp(node->name, "input")) {
8208 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8209 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008210 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008211 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008212 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008213 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008214 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008215 } else if (!strcmp(node->name, "notification")) {
8216 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8217 } else if (!strcmp(node->name, "uses")) {
8218 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008219 } else if (!strcmp(node->name, "length")) {
8220 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8221 } else if (!strcmp(node->name, "must")) {
8222 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8223 if (!pp) {
8224 goto error;
8225 }
8226 /* allocate structure for must */
8227 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008228 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008229
8230 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8231 goto error;
8232 }
8233 } else if (!strcmp(node->name, "pattern")) {
8234 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008235 GETVAL(mod->ctx, value, node, "value");
8236 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008237 goto error;
8238 }
8239
8240 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008241 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008242
8243 modifier = 0x06; /* ACK */
8244 if (mod->version >= 2) {
8245 name = NULL;
8246 LY_TREE_FOR(node->child, child) {
8247 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8248 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008249 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008250 goto error;
8251 }
8252
Michal Vasko53b7da02018-02-13 15:28:42 +01008253 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008254 if (!strcmp(name, "invert-match")) {
8255 modifier = 0x15; /* NACK */
8256 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008257 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008258 goto error;
8259 }
8260 /* get extensions of the modifier */
8261 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8262 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8263 goto error;
8264 }
8265 }
8266 }
8267 }
8268
8269 /* store the value: modifier byte + value + terminating NULL byte */
8270 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008271 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008272 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8273 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8274 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8275
8276 /* get possible sub-statements */
8277 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8278 goto error;
8279 }
8280
8281 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8282 } else if (!strcmp(node->name, "range")) {
8283 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008284 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008285 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008286 }
8287 lyxml_free(mod->ctx, node);
8288 }
8289
PavolVicanc4b798e2017-02-20 23:15:27 +01008290 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8291 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008292 }
8293
Radek Krejci8d6b7422017-02-03 14:42:13 +01008294 return EXIT_SUCCESS;
8295
8296error:
8297 return EXIT_FAILURE;
8298}