blob: 130ba3f828adcb50be9036221429ec445dcea9e2 [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 Krejciaf351422015-06-19 14:49:38 +02001208 if (!strcmp(node->name, "require-instance")) {
1209 if (type->info.inst.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001210 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001211 goto error;
1212 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001213 GETVAL(ctx, value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001214 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001215 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001216 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001217 type->info.inst.req = -1;
1218 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001219 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001220 goto error;
1221 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001222
1223 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001224 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001225 goto error;
1226 }
Radek Krejciaf351422015-06-19 14:49:38 +02001227 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001228 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001229 goto error;
1230 }
Radek Krejciaf351422015-06-19 14:49:38 +02001231 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001232
Michal Vaskod439b2a2020-05-04 17:45:14 +02001233 if (type->der->type.der && !type->info.inst.req) {
1234 /* inherit require-instance property */
1235 type->info.inst.req = type->der->type.info.inst.req;
1236 }
1237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 break;
1239
Radek Krejcif2860132015-06-20 12:37:20 +02001240 case LY_TYPE_BINARY:
1241 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001242 case LY_TYPE_INT8:
1243 case LY_TYPE_INT16:
1244 case LY_TYPE_INT32:
1245 case LY_TYPE_INT64:
1246 case LY_TYPE_UINT8:
1247 case LY_TYPE_UINT16:
1248 case LY_TYPE_UINT32:
1249 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001250 /* RFC 6020 9.2.4 - range */
1251
1252 /* length and range are actually the same restriction, so process
1253 * them by this common code, we just need to differ the name and
1254 * structure where the information will be stored
1255 */
1256 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001257 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001258 name = "length";
1259 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001260 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001261 name = "range";
1262 }
1263
Radek Krejci73adb602015-07-02 18:07:40 +02001264 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001265
Radek Krejcif2860132015-06-20 12:37:20 +02001266 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001267 if (*restrs) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001268 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001269 goto error;
1270 }
1271
Michal Vasko53b7da02018-02-13 15:28:42 +01001272 GETVAL(ctx, value, node, "value");
1273 if (lyp_check_length_range(ctx, value, type)) {
1274 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001275 goto error;
1276 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001277 *restrs = calloc(1, sizeof **restrs);
Michal Vasko53b7da02018-02-13 15:28:42 +01001278 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM(ctx), error);
1279 (*restrs)->expr = lydict_insert(ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001280
1281 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001282 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001283 goto error;
1284 }
PavolVican92f23622017-12-12 13:35:56 +01001285
1286 for (j = 0; j < (*restrs)->ext_size; ++j) {
1287 /* set flag, which represent LYEXT_OPT_VALID */
1288 if ((*restrs)->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001289 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001290 break;
1291 }
1292 }
Radek Krejcif2860132015-06-20 12:37:20 +02001293 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001294 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001295 goto error;
1296 }
Radek Krejcif2860132015-06-20 12:37:20 +02001297 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298 break;
1299
1300 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001301 /* flag resolving for later use */
Michal Vaskoa2049012019-07-18 13:26:29 +02001302 if (!parenttype && lys_ingrouping(parent)) {
1303 /* just a flag - do not resolve */
1304 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001305 }
1306
Radek Krejcidc4c1412015-06-19 15:39:54 +02001307 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001308 LY_TREE_FOR(yin->child, node) {
Michal Vasko7560ac42019-07-01 08:54:59 +02001309 if (!strcmp(node->name, "path") && !type->der->type.der) {
1310 /* keep path for later */
Michal Vaskod439b2a2020-05-04 17:45:14 +02001311 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko7560ac42019-07-01 08:54:59 +02001312 if (type->info.lref.req) {
1313 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1314 goto error;
1315 }
1316 GETVAL(ctx, value, node, "value");
1317 if (!strcmp(value, "true")) {
1318 type->info.lref.req = 1;
1319 } else if (!strcmp(value, "false")) {
1320 type->info.lref.req = -1;
1321 } else {
1322 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1323 goto error;
1324 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001325
Michal Vasko7560ac42019-07-01 08:54:59 +02001326 /* extensions */
1327 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
1328 goto error;
1329 }
1330 } else {
1331 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1332 goto error;
1333 }
1334 }
1335
1336 /* now that require-instance is properly set, try to find and resolve path */
1337 LY_TREE_FOR(yin->child, node) {
Michal Vasko88c29542015-11-27 14:57:53 +01001338 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001339 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001340 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001341 goto error;
1342 }
1343
Michal Vasko53b7da02018-02-13 15:28:42 +01001344 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001345 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001346 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001347 if (!type->info.lref.path) {
1348 goto error;
1349 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001350
1351 /* try to resolve leafref path only when this is instantiated
1352 * leaf, so it is not:
1353 * - typedef's type,
1354 * - in grouping definition,
1355 * - just instantiated in a grouping definition,
1356 * because in those cases the nodes referenced in path might not be present
1357 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001358 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001359 goto error;
1360 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001361
1362 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001363 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001364 goto error;
1365 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001366
Michal Vasko7560ac42019-07-01 08:54:59 +02001367 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001368 }
Radek Krejci73adb602015-07-02 18:07:40 +02001369 }
1370
Radek Krejci742be352016-07-17 12:18:54 +02001371 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001372 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001373 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001374 goto error;
1375 } else {
1376 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001377 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Michal Vaskod439b2a2020-05-04 17:45:14 +02001378 if (!type->info.lref.req) {
1379 type->info.lref.req = type->der->type.info.lref.req;
1380 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001381 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001382 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001383 goto error;
1384 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001385 }
Radek Krejci742be352016-07-17 12:18:54 +02001386 }
1387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001388 break;
1389
1390 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001391 /* RFC 6020 9.4.4 - length */
1392 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001393 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001394 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001395
Radek Krejci3733a802015-06-19 13:43:21 +02001396 if (!strcmp(node->name, "length")) {
1397 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001398 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001399 goto error;
1400 }
1401
Michal Vasko53b7da02018-02-13 15:28:42 +01001402 GETVAL(ctx, value, node, "value");
1403 if (lyp_check_length_range(ctx, value, type)) {
1404 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001405 goto error;
1406 }
1407 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001408 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1409 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001410
Radek Krejci5fbc9162015-06-19 14:11:11 +02001411 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001412 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001413 goto error;
1414 }
PavolVican92f23622017-12-12 13:35:56 +01001415
1416 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1417 /* set flag, which represent LYEXT_OPT_VALID */
1418 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001419 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001420 break;
1421 }
1422 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001423 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001424 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001425 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001426 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001427 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001428 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001429 goto error;
1430 }
1431 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001432 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001433 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001434 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001435 in_grp = 1;
1436 }
Radek Krejci73adb602015-07-02 18:07:40 +02001437 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001438 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001439#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001440 if (!in_grp) {
1441 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001442 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001443 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001444 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001445#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001446 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001447 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001448
Michal Vasko9c7dee32018-07-09 09:12:59 +02001449 if (in_grp) {
1450 /* in grouping, just check the pattern syntax */
1451 if (!(ctx->models.flags & LY_CTX_TRUSTED) && lyp_check_pattern(ctx, value, NULL)) {
1452 goto error;
Radek Krejcib53154b2017-07-19 09:14:13 +02001453 }
Michal Vasko69068852015-07-13 14:34:31 +02001454 }
Michal Vasko9c7dee32018-07-09 09:12:59 +02001455#ifdef LY_ENABLED_CACHE
1456 else {
1457 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
1458 if (lyp_precompile_pattern(ctx, value,
1459 (pcre **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1460 (pcre_extra **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1461 goto error;
1462 }
1463 }
1464#endif
Radek Krejcifccd1442017-01-16 10:26:57 +01001465 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001466 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001467
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001468 modifier = 0x06; /* ACK */
1469 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001470 if (module->version >= 2) {
1471 LY_TREE_FOR_SAFE(node->child, next2, child) {
1472 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1473 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001474 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001475 goto error;
1476 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001477
Michal Vasko53b7da02018-02-13 15:28:42 +01001478 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001479 if (!strcmp(name, "invert-match")) {
1480 modifier = 0x15; /* NACK */
1481 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001482 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001483 goto error;
1484 }
1485 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001486 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001487 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1488 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001489 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001490
Michal Vasko53b7da02018-02-13 15:28:42 +01001491 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001492 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001493 }
1494 }
1495
1496 len = strlen(value);
1497 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001498 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001499 buf[0] = modifier;
1500 strcpy(&buf[1], value);
1501
Michal Vasko53b7da02018-02-13 15:28:42 +01001502 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001503
1504 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001505 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001506 goto error;
1507 }
PavolVican92f23622017-12-12 13:35:56 +01001508
1509 for (j = 0; j < restr->ext_size; ++j) {
1510 /* set flag, which represent LYEXT_OPT_VALID */
1511 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001512 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001513 break;
1514 }
1515 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001516 }
1517 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001518 break;
1519
1520 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001521 /* RFC 6020 7.4 - type */
1522 /* count number of types in union */
1523 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001524 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001525
Radek Krejcie4c366b2015-07-02 10:11:31 +02001526 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001527 if (type->der->type.der) {
1528 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001529 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001530 goto error;
1531 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001532 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001533 i++;
1534 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001535 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001536 goto error;
1537 }
1538 }
1539
Radek Krejci038d5d92016-09-12 15:07:15 +02001540 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001541 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001542 goto error;
1543 }
1544
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001545 /* inherit instid presence information */
1546 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1547 type->info.uni.has_ptr_type = 1;
1548 }
1549
Radek Krejcie4c366b2015-07-02 10:11:31 +02001550 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001551 if (i) {
1552 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001553 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001554 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001555
Radek Krejcie4c366b2015-07-02 10:11:31 +02001556 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001557 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001558 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001559 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001560 if (!rc) {
1561 type->info.uni.count++;
1562
Radek Krejci7de36cf2016-09-12 16:18:50 +02001563 if (module->version < 2) {
1564 /* union's type cannot be empty or leafref */
1565 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001566 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001567 rc = -1;
1568 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001569 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001570 rc = -1;
1571 }
Michal Vasko88c29542015-11-27 14:57:53 +01001572 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001573
1574 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001575 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1576 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1577 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001578 type->info.uni.has_ptr_type = 1;
1579 }
Michal Vasko88c29542015-11-27 14:57:53 +01001580 }
1581 if (rc) {
1582 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1583 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001584 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001585 }
1586 free(type->info.uni.types);
1587 type->info.uni.types = NULL;
1588 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001589 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001590 type->der = NULL;
1591 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001592
1593 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001594 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001595 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001596 goto error;
1597 }
Michal Vasko88c29542015-11-27 14:57:53 +01001598 }
1599 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001600
Michal Vasko88c29542015-11-27 14:57:53 +01001601 case LY_TYPE_BOOL:
1602 case LY_TYPE_EMPTY:
1603 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001604 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001605 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001606 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001607 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 break;
1609
1610 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001611 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001612 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 }
1614
PavolVican92f23622017-12-12 13:35:56 +01001615 for(j = 0; j < type->ext_size; ++j) {
1616 /* set flag, which represent LYEXT_OPT_VALID */
1617 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001618 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001619 break;
1620 }
1621 }
1622
1623 /* if derived type has extension, which need validate data */
1624 dertype = &type->der->type;
1625 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001626 if (dertype->parent->flags & LYS_VALID_EXT) {
1627 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001628 }
1629 dertype = &dertype->der->type;
1630 }
1631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001632 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001633
1634error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001635 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001636 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001637}
1638
Michal Vasko0d343d12015-08-24 14:57:36 +02001639/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001641fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1642 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001643{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001645 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001646 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001647 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001648 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001649
Michal Vasko53b7da02018-02-13 15:28:42 +01001650 GETVAL(ctx, value, yin, "name");
1651 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 goto error;
1653 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001654 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001656 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001657 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 goto error;
1659 }
Radek Krejcieac35532015-05-31 19:09:15 +02001660
Michal Vasko88c29542015-11-27 14:57:53 +01001661 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001662 if (strcmp(node->ns->value, LY_NSYIN)) {
1663 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001664 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001665 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001666 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001667 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001668 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001669 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 goto error;
1671 }
Michal Vasko88c29542015-11-27 14:57:53 +01001672 /* HACK for unres */
1673 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001674 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001675 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001676 goto error;
1677 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001678 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001679
Radek Krejci07d0fb92017-01-13 14:11:05 +01001680 /* 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 +01001681 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001682 } else if (!strcmp(node->name, "default")) {
1683 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001684 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001685 goto error;
1686 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001687 GETVAL(ctx, value, node, "value");
1688 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001689
Radek Krejci8d6b7422017-02-03 14:42:13 +01001690 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001691 goto error;
1692 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001693 } else if (!strcmp(node->name, "units")) {
1694 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001695 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 goto error;
1697 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001698 GETVAL(ctx, value, node, "name");
1699 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001700
Radek Krejci8d6b7422017-02-03 14:42:13 +01001701 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001702 goto error;
1703 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001705 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001706 goto error;
1707 }
Radek Krejcie534c132016-11-23 13:32:31 +01001708
Michal Vasko53b7da02018-02-13 15:28:42 +01001709 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001710 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001713 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001714 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001715 goto error;
1716 }
Radek Krejcieac35532015-05-31 19:09:15 +02001717
Michal Vasko478c4652016-07-21 12:55:01 +02001718 /* check default value (if not defined, there still could be some restrictions
1719 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001720 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001721 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001722 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001723 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001724
Radek Krejcie534c132016-11-23 13:32:31 +01001725 /* finish extensions parsing */
1726 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001727 /* some extensions may be already present from the substatements */
1728 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001729 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001730 tpdf->ext = reallocated;
1731
1732 /* init memory */
1733 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1734
Radek Krejcie534c132016-11-23 13:32:31 +01001735 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001736 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 +01001737 tpdf->ext_size++;
1738 if (rc) {
1739 goto error;
1740 }
1741 }
1742 }
1743
PavolVican92f23622017-12-12 13:35:56 +01001744 for (i = 0; i < tpdf->ext_size; ++i) {
1745 /* set flag, which represent LYEXT_OPT_VALID */
1746 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001747 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001748 break;
1749 }
1750 }
1751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001753
1754error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001756}
1757
Radek Krejcia1a6b762016-11-14 09:53:38 +09001758static int
Radek Krejcie534c132016-11-23 13:32:31 +01001759fill_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 +09001760{
Michal Vasko53b7da02018-02-13 15:28:42 +01001761 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001762 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001763 struct lyxml_elem *child, *node, *next, *next2;
1764 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001765 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001766
Michal Vasko53b7da02018-02-13 15:28:42 +01001767 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001768
Michal Vasko53b7da02018-02-13 15:28:42 +01001769 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001770 goto error;
1771 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001772 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001773
Radek Krejci07d0fb92017-01-13 14:11:05 +01001774 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001775 goto error;
1776 }
1777
Radek Krejcie534c132016-11-23 13:32:31 +01001778 LY_TREE_FOR_SAFE(yin->child, next, node) {
1779 if (strcmp(node->ns->value, LY_NSYIN)) {
1780 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001781 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001782 c_ext++;
1783 } else if (!strcmp(node->name, "argument")) {
1784 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001785 GETVAL(ctx, value, node, "name");
1786 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001787 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001788 goto error;
1789 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001790
Radek Krejcia1a6b762016-11-14 09:53:38 +09001791 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001792 LY_TREE_FOR_SAFE(node->child, next2, child) {
1793 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001794 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001795 if (ly_strequal(value, "true", 0)) {
1796 ext->flags |= LYS_YINELEM;
1797 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001798
Radek Krejci8d6b7422017-02-03 14:42:13 +01001799 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001800 goto error;
1801 }
Radek Krejcie534c132016-11-23 13:32:31 +01001802 } else if (child->ns) {
1803 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001804 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001805 goto error;
1806 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001807 }
1808
Michal Vasko53b7da02018-02-13 15:28:42 +01001809 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001810 } else {
1811 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001812 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001813 goto error;
1814 }
1815 }
1816
1817 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001818 /* some extensions may be already present from the substatements */
1819 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001820 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001821 ext->ext = reallocated;
1822
1823 /* init memory */
1824 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1825
1826 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001827 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001828 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 +01001829 ext->ext_size++;
1830 if (rc) {
1831 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001832 }
1833 }
1834 }
1835
Radek Krejci0a498f82017-01-04 16:24:15 +01001836 /* search for plugin */
1837 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 +09001838
1839 return EXIT_SUCCESS;
1840
1841error:
1842 return EXIT_FAILURE;
1843}
1844
Michal Vasko0d343d12015-08-24 14:57:36 +02001845/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001846static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001847fill_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 +02001848{
Michal Vasko53b7da02018-02-13 15:28:42 +01001849 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001850 const char *value;
1851 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001852 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001853 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001854
Michal Vasko53b7da02018-02-13 15:28:42 +01001855 GETVAL(ctx, value, yin, "name");
1856 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001857 goto error;
1858 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001859 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001860 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001861
Radek Krejci07d0fb92017-01-13 14:11:05 +01001862 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001863 goto error;
1864 }
1865
Radek Krejcie534c132016-11-23 13:32:31 +01001866 LY_TREE_FOR(yin->child, child) {
1867 if (strcmp(child->ns->value, LY_NSYIN)) {
1868 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001869 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001870 c_ext++;
1871 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001872 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001873 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001874 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001875 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001876 goto error;
1877 }
1878 }
1879
Radek Krejcie534c132016-11-23 13:32:31 +01001880 if (c_ftrs) {
1881 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001882 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001883 }
Radek Krejcie534c132016-11-23 13:32:31 +01001884 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001885 /* some extensions may be already present from the substatements */
1886 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001887 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001888 f->ext = reallocated;
1889
1890 /* init memory */
1891 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001892 }
1893
Radek Krejcie534c132016-11-23 13:32:31 +01001894 LY_TREE_FOR_SAFE(yin->child, next, child) {
1895 if (strcmp(child->ns->value, LY_NSYIN)) {
1896 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001897 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 +01001898 f->ext_size++;
1899 if (ret) {
1900 goto error;
1901 }
1902 } else { /* if-feature */
1903 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1904 f->iffeature_size++;
1905 if (ret) {
1906 goto error;
1907 }
1908 }
1909 }
1910
Radek Krejcic79c6b12016-07-26 15:11:49 +02001911 /* check for circular dependencies */
1912 if (f->iffeature_size) {
1913 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1914 goto error;
1915 }
1916 }
1917
Radek Krejci3cf9e222015-06-18 11:37:50 +02001918 return EXIT_SUCCESS;
1919
1920error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001921 return EXIT_FAILURE;
1922}
1923
Michal Vasko0d343d12015-08-24 14:57:36 +02001924/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001926fill_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 +02001927{
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001928 int ret = EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001929 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001930
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001931 must->expr = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01001932 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001933 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001934 if (!must->expr) {
1935 goto error;
1936 }
Radek Krejci800af702015-06-02 13:46:01 +02001937
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001938 ret = read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001939
Michal Vasko77dc5652016-02-15 12:32:42 +01001940error:
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001941 if (ret) {
1942 lydict_remove(module->ctx, must->expr);
1943 must->expr = NULL;
1944 }
1945 return ret;
Radek Krejci800af702015-06-02 13:46:01 +02001946}
1947
Radek Krejci581ce772015-11-10 17:22:40 +01001948static int
Radek Krejci7417a082017-02-16 11:07:59 +01001949fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1950 struct unres_schema *unres)
1951{
Michal Vasko53b7da02018-02-13 15:28:42 +01001952 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001953 struct lyxml_elem *next, *child;
1954 const char *value;
1955
Michal Vasko53b7da02018-02-13 15:28:42 +01001956 GETVAL(ctx, value, yin, "date");
1957 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001958 goto error;
1959 }
1960 memcpy(rev->date, value, LY_REV_SIZE - 1);
1961
1962 LY_TREE_FOR_SAFE(yin->child, next, child) {
1963 if (!child->ns) {
1964 /* garbage */
1965 continue;
1966 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1967 /* possible extension instance */
1968 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1969 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1970 goto error;
1971 }
1972 } else if (!strcmp(child->name, "description")) {
1973 if (rev->dsc) {
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_DESCRIPTION, 0, unres)) {
1979 goto error;
1980 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001981 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001982 if (!rev->dsc) {
1983 goto error;
1984 }
1985 } else if (!strcmp(child->name, "reference")) {
1986 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001987 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001988 goto error;
1989 }
1990 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1991 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1992 goto error;
1993 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001994 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001995 if (!rev->ref) {
1996 goto error;
1997 }
1998 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001999 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01002000 goto error;
2001 }
2002 }
2003
2004 return EXIT_SUCCESS;
2005
2006error:
2007 return EXIT_FAILURE;
2008}
2009
2010static int
Michal Vasko88c29542015-11-27 14:57:53 +01002011fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
2012 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01002013{
Michal Vasko53b7da02018-02-13 15:28:42 +01002014 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02002015 int i, j, ret = EXIT_FAILURE;
2016 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02002017 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002018 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01002019
2020 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01002021 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01002022
2023 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002024 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01002025 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002026 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002027 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02002028 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01002029 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01002030 while (isspace(*vaux)) {
2031 vaux++;
2032 }
2033 }
2034 unique->expr_size++;
2035 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002036 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002037
2038 for (i = 0; i < unique->expr_size; i++) {
2039 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02002040 if (vaux) {
2041 c = *vaux;
2042 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01002043 }
2044
2045 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002046 unique->expr[i] = transform_schema2json(module, value);
2047 if (vaux) {
2048 *vaux = c;
2049 }
Radek Krejci581ce772015-11-10 17:22:40 +01002050
2051 /* check that the expression does not repeat */
2052 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002053 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002054 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
2055 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01002056 goto error;
2057 }
2058 }
2059
2060 /* try to resolve leaf */
2061 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002062 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01002063 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02002064 unique_info->list = parent;
2065 unique_info->expr = unique->expr[i];
2066 unique_info->trg_type = &unique->trg_type;
2067 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02002068 goto error;
2069 }
Radek Krejci581ce772015-11-10 17:22:40 +01002070 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002071 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002072 goto error;
2073 }
2074 }
2075
2076 /* move to next token */
2077 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002078 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002079 value++;
2080 }
2081 }
2082
Radek Krejci1a9c3612017-04-24 14:49:43 +02002083 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002084
2085error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002086 free(start);
2087 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002088}
2089
Michal Vasko0d343d12015-08-24 14:57:36 +02002090/* logs directly
2091 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002092 * type: 0 - min, 1 - max
2093 */
2094static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002095deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002096{
2097 const char *value;
2098 char *endptr;
2099 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002100 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002101 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002102
Michal Vaskof7e57d52016-03-07 11:31:09 +01002103 /* del min/max is forbidden */
2104 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002105 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002106 goto error;
2107 }
2108
Radek Krejcieb00f512015-07-01 16:44:58 +02002109 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002110 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002111 max = &((struct lys_node_leaflist *)target)->max;
2112 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002113 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002114 max = &((struct lys_node_list *)target)->max;
2115 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002116 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002117 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2118 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002119 goto error;
2120 }
2121
Michal Vasko53b7da02018-02-13 15:28:42 +01002122 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002123 while (isspace(value[0])) {
2124 value++;
2125 }
2126
Radek Krejci0d7b2472016-02-12 11:11:03 +01002127 if (type && !strcmp(value, "unbounded")) {
2128 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002129 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002130 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002131 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002132 /* convert it to uint32_t */
2133 errno = 0;
2134 endptr = NULL;
2135 val = strtoul(value, &endptr, 10);
2136 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002137 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002138 goto error;
2139 }
2140 if (type) {
2141 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002142 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002143 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002144 } else {
2145 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002146 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002147 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002148 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002149 }
2150
2151 if (d->mod == LY_DEVIATE_ADD) {
2152 /* check that there is no current value */
2153 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002154 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2155 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002156 goto error;
2157 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002158 } else if (d->mod == LY_DEVIATE_RPL) {
2159 /* unfortunately, there is no way to check reliably that there
2160 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002161 }
2162
Michal Vaskof7e57d52016-03-07 11:31:09 +01002163 /* add (already checked) and replace */
2164 /* set new value specified in deviation */
2165 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002166
Pavol Vican09adcc32016-08-25 10:51:36 +02002167 /* check min-elements is smaller than max-elements */
2168 if (*max && *min > *max) {
2169 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002170 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2171 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002172 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002173 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2174 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002175 }
2176 goto error;
2177 }
2178
Radek Krejcieb00f512015-07-01 16:44:58 +02002179 return EXIT_SUCCESS;
2180
2181error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002182 return EXIT_FAILURE;
2183}
2184
Michal Vasko0d343d12015-08-24 14:57:36 +02002185/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002186static int
Michal Vasko88c29542015-11-27 14:57:53 +01002187fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2188 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002189{
2190 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002191 struct lyxml_elem *next, *next2, *child, *develem;
2192 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002193 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002194 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002195 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002196 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002197 struct lys_deviate *d = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002198 struct lys_node *node, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002199 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002200 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002201 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002202 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002203 struct lys_node_leaflist *llist = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002204 struct lys_node_inout *inout;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002205 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002206 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002207 struct lys_restr **trg_must = NULL;
Michal Vasko49c709c2020-01-30 14:32:22 +01002208 struct unres_schema *tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002209 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002210 void *reallocated;
Andrew Langefeldf9763242018-09-16 22:23:50 -05002211 size_t deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002212
Michal Vasko53b7da02018-02-13 15:28:42 +01002213 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002214 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002215 if (!dev->target_name) {
2216 goto error;
2217 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002218
2219 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002220 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2221 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002222 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002223 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002224 goto error;
2225 }
Michal Vasko50576712017-07-28 12:28:33 +02002226 dev_target = set->set.s[0];
2227 ly_set_free(set);
2228
Radek Krejcic4283442016-04-22 09:19:27 +02002229 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002230 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2231 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002232 goto error;
2233 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002234
2235 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002236 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002237 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002238 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002239 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002240 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2241 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002242 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002243 c_ext++;
2244 continue;
2245 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002246 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002247 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002248 goto error;
2249 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002250 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002251 goto error;
2252 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002253 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002254 if (!dev->dsc) {
2255 goto error;
2256 }
2257 } else if (!strcmp(child->name, "reference")) {
2258 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002259 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002260 goto error;
2261 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002262 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002263 goto error;
2264 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002265 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002266 if (!dev->ref) {
2267 goto error;
2268 }
2269 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002270 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002271 c_dev++;
2272
Michal Vasko345da0a2015-12-02 10:35:55 +01002273 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002274 * further processed later
2275 */
2276 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002277
Radek Krejcieb00f512015-07-01 16:44:58 +02002278 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002279 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002280 goto error;
2281 }
2282
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002283 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002284 }
2285
2286 if (c_dev) {
2287 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002288 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002289 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002290 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002291 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002292 }
Radek Krejcie534c132016-11-23 13:32:31 +01002293 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002294 /* some extensions may be already present from the substatements */
2295 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002296 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002297 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002298
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002299 /* init memory */
2300 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2301 }
Radek Krejcie534c132016-11-23 13:32:31 +01002302
2303 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2304 if (strcmp(develem->ns->value, LY_NSYIN)) {
2305 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002306 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 +01002307 dev->ext_size++;
2308 if (rc) {
2309 goto error;
2310 }
2311 continue;
2312 }
2313
2314 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002315 /* init */
2316 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002317 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002318 c_must = 0;
2319 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002320 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002321 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002322
2323 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002324 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002325 if (!strcmp(value, "not-supported")) {
2326 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002327 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002328 * not-supported deviation must be the only deviation of the target
2329 */
2330 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002331 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2332 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 +02002333 goto error;
2334 }
2335
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002336 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002337 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2338 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2339 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002340 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2341 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002342 goto error;
2343 }
2344 }
2345 }
Radek Krejci5b917642015-07-02 09:03:13 +02002346
Michal Vaskoff006c12016-02-17 11:15:19 +01002347 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002348 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002349 lys_node_unlink(dev_target);
Michal Vasko5df038e2018-08-02 09:41:26 +02002350 if (parent) {
2351 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
2352 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2353 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2354 * path), so we need to remember the augment as an addition */
2355 /* remember uses parent so we can reconnect to it */
2356 dev_target->parent = parent;
2357 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
2358 /* re-create implicit node */
2359 inout = calloc(1, sizeof *inout);
2360 LY_CHECK_ERR_GOTO(!inout, LOGMEM(ctx), error);
2361
2362 inout->nodetype = dev_target->nodetype;
2363 inout->name = lydict_insert(ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
2364 inout->module = dev_target->module;
2365 inout->flags = LYS_IMPLICIT;
2366
2367 /* insert it manually */
2368 assert(parent->child && !parent->child->next
2369 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
2370 parent->child->next = (struct lys_node *)inout;
2371 inout->prev = parent->child;
2372 parent->child->prev = (struct lys_node *)inout;
2373 inout->parent = parent;
2374 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01002375 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002376 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002377
Radek Krejcieb00f512015-07-01 16:44:58 +02002378 } else if (!strcmp(value, "add")) {
2379 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2380 } else if (!strcmp(value, "replace")) {
2381 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2382 } else if (!strcmp(value, "delete")) {
2383 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2384 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002385 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002386 goto error;
2387 }
2388 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002389 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002390
Michal Vaskoff006c12016-02-17 11:15:19 +01002391 /* store a shallow copy of the original node */
2392 if (!dev->orig_node) {
Michal Vasko49c709c2020-01-30 14:32:22 +01002393 tmp_unres = calloc(1, sizeof *tmp_unres);
2394 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, tmp_unres, 1);
2395 /* such a case is not really supported but whatever */
2396 unres_schema_free(dev_target->module, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002397 }
2398
Radek Krejcieb00f512015-07-01 16:44:58 +02002399 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002400 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002401 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002402 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002403 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002404 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002405 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2406 /* extensions */
Michal Vasko53b7da02018-02-13 15:28:42 +01002407 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, d->ext_size, "extensions", "deviate", error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002408 c_ext++;
2409 } else if (d->mod == LY_DEVIATE_NO) {
2410 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002411 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002412 goto error;
2413 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002414 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002415 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002416 goto error;
2417 }
2418
2419 /* for we deviate from RFC 6020 and allow config property even it is/is not
2420 * specified in the target explicitly since config property inherits. So we expect
2421 * that config is specified in every node. But for delete, we check that the value
2422 * is the same as here in deviation
2423 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002424 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002425 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002426 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002427 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002428 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002429 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002430 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002431 goto error;
2432 }
2433
2434 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002435 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002436 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002437 goto error;
Michal Vasko9bc467e2020-01-06 10:09:44 +01002438 } else if ((d->mod == LY_DEVIATE_ADD) && (dev_target->flags & LYS_CONFIG_SET)) {
2439 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
2440 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2441 goto error;
2442 } else if ((d->mod == LY_DEVIATE_RPL) && !(dev_target->flags & LYS_CONFIG_SET)) {
2443 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
2444 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2445 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002446 } else { /* add and replace are the same in this case */
2447 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002448 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002449
2450 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002451 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002452 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002453
Radek Krejci8d6b7422017-02-03 14:42:13 +01002454 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002455 goto error;
2456 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002457 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002458 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 +01002459 goto error;
2460 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002461 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002462 c_dflt++;
2463
2464 /* check target node type */
2465 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002466 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2467 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002468 goto error;
2469 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002470 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2471 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002472 goto error;
2473 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002474 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2475 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002476 goto error;
2477 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002478
Radek Krejcid5a5c282016-08-15 15:38:08 +02002479 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2480 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002481
Radek Krejcieb00f512015-07-01 16:44:58 +02002482 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002483 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002484 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002485 goto error;
2486 }
2487
2488 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002489 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
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, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002492 goto error;
2493 }
2494
Michal Vasko53b7da02018-02-13 15:28:42 +01002495 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002496 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002497 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002498 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002499 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002500 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002501 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002502 goto error;
2503 }
2504
2505 if (d->mod == LY_DEVIATE_ADD) {
2506 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002507 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002508 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2509 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002510 goto error;
2511 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002512
Radek Krejci841ec082016-04-05 13:05:17 +02002513 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002514 if (d->flags & LYS_MAND_TRUE) {
2515 if (dev_target->nodetype == LYS_CHOICE) {
2516 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002517 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2518 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002519 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2520 goto error;
2521 }
2522 } else if (dev_target->nodetype == LYS_LEAF) {
2523 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002524 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2525 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002526 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2527 goto error;
2528 }
2529 }
Radek Krejci841ec082016-04-05 13:05:17 +02002530 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002531
Michal Vasko21be1b32016-03-07 12:31:34 +01002532 dev_target->flags |= d->flags & LYS_MAND_MASK;
2533 } else if (d->mod == LY_DEVIATE_RPL) {
2534 /* check that there was a value before */
2535 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002536 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2537 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002538 goto error;
2539 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002540
Michal Vasko21be1b32016-03-07 12:31:34 +01002541 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002542 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002543 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002544 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002545 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002546 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002547 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002548
2549 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2550 for (parent = dev_target->parent;
2551 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2552 parent = parent->parent) {
2553 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2554 /* stop also on presence containers */
2555 break;
2556 }
2557 }
2558 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2559 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2560 if (lyp_check_mandatory_choice(parent)) {
2561 goto error;
2562 }
2563 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002564
Radek Krejci8d6b7422017-02-03 14:42:13 +01002565 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002566 goto error;
2567 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002568 } else if (!strcmp(child->name, "min-elements")) {
2569 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002570 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002571 goto error;
2572 }
2573 f_min = 1;
2574
Michal Vasko60f4b452016-02-12 11:02:55 +01002575 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002576 goto error;
2577 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002578 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002579 goto error;
2580 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002581 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002582 if (f_max) {
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 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002586 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002587
Michal Vasko60f4b452016-02-12 11:02:55 +01002588 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002589 goto error;
2590 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002591 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002592 goto error;
2593 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002594 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002595 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002596 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002597 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002598 continue;
2599 } else if (!strcmp(child->name, "type")) {
2600 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002601 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002602 goto error;
2603 }
2604
Michal Vaskof7e57d52016-03-07 11:31:09 +01002605 /* add, del type is forbidden */
2606 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002607 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002608 goto error;
2609 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002610 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002611 goto error;
2612 }
2613
Radek Krejcieb00f512015-07-01 16:44:58 +02002614 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002615 if (dev_target->nodetype == LYS_LEAF) {
2616 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002617 if (((struct lys_node_leaf *)dev_target)->dflt) {
2618 ly_set_add(dflt_check, dev_target, 0);
2619 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002620 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2621 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002622 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2623 ly_set_add(dflt_check, dev_target, 0);
2624 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002625 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002626 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2627 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002628 goto error;
2629 }
2630
Radek Krejcieb00f512015-07-01 16:44:58 +02002631 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002632 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002633 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002634 /* HACK for unres */
2635 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002636 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002637 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002638 goto error;
2639 }
2640 d->type = t;
2641 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002642 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 +01002643 goto error;
2644 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002645 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002646 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002647 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002648 continue;
2649 } else if (!strcmp(child->name, "units")) {
2650 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002651 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002652 goto error;
2653 }
2654
2655 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002656 if (dev_target->nodetype == LYS_LEAFLIST) {
2657 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2658 } else if (dev_target->nodetype == LYS_LEAF) {
2659 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002660 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002661 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2662 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002663 goto error;
2664 }
2665
2666 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002667 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002668 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002669
2670 /* apply to target */
2671 if (d->mod == LY_DEVIATE_ADD) {
2672 /* check that there is no current value */
2673 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002674 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2675 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002676 goto error;
2677 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002678
Michal Vasko21be1b32016-03-07 12:31:34 +01002679 *stritem = lydict_insert(ctx, value, 0);
2680 } else if (d->mod == LY_DEVIATE_RPL) {
2681 /* check that there was a value before */
2682 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002683 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2684 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002685 goto error;
2686 }
2687
2688 lydict_remove(ctx, *stritem);
2689 *stritem = lydict_insert(ctx, value, 0);
2690 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002691 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002692 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002693 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2694 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002695 goto error;
2696 }
2697 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002698 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002699 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002700
2701 /* remove its extensions */
2702 j = -1;
2703 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2704 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2705 --j;
2706 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002707 }
2708
Radek Krejci8d6b7422017-02-03 14:42:13 +01002709 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002710 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002711 }
2712 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002713 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002714 goto error;
2715 }
2716
Michal Vasko88c29542015-11-27 14:57:53 +01002717 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002718 }
2719
2720 if (c_must) {
2721 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002722 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002723 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002724 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2725 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002726 break;
Radek Krejci76512572015-08-04 09:47:08 +02002727 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002728 trg_must = &((struct lys_node_container *)dev_target)->must;
2729 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002730 break;
Radek Krejci76512572015-08-04 09:47:08 +02002731 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002732 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2733 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002734 break;
Radek Krejci76512572015-08-04 09:47:08 +02002735 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002736 trg_must = &((struct lys_node_list *)dev_target)->must;
2737 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002738 break;
Radek Krejci76512572015-08-04 09:47:08 +02002739 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002740 case LYS_ANYDATA:
2741 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2742 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002743 break;
2744 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002745 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2746 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002747 goto error;
2748 }
2749
Michal Vaskoc04173b2018-03-09 10:43:22 +01002750 dev_target->flags &= ~(LYS_XPCONF_DEP | LYS_XPSTATE_DEP);
Michal Vasko508a50d2016-09-07 14:50:33 +02002751
Radek Krejcieb00f512015-07-01 16:44:58 +02002752 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002753 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002754 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002755 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002756 } else if (d->mod == LY_DEVIATE_ADD) {
2757 /* reallocate the must array of the target */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002758 struct lys_restr *must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
2759 LY_CHECK_ERR_GOTO(!must, LOGMEM(ctx), error);
2760 *trg_must = must;
2761 d->must = calloc(c_must, sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02002762 d->must_size = c_must;
2763 } else { /* LY_DEVIATE_DEL */
2764 d->must = calloc(c_must, sizeof *d->must);
2765 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002766 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002767 }
2768 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002769 /* replace unique is forbidden */
2770 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002771 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002772 goto error;
2773 }
2774
Radek Krejcieb00f512015-07-01 16:44:58 +02002775 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002776 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002777 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2778 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002779 goto error;
2780 }
2781
Michal Vasko60f4b452016-02-12 11:02:55 +01002782 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002783 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002784 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002785 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002786 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002787 list->unique = d->unique;
2788 d->unique = &list->unique[list->unique_size];
2789 d->unique_size = c_uniq;
2790 } else { /* LY_DEVIATE_DEL */
2791 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002792 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002793 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002794 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002795 if (c_dflt) {
2796 if (d->mod == LY_DEVIATE_ADD) {
2797 /* check that there is no current value */
2798 if ((dev_target->nodetype == LYS_LEAF && ((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, "default");
2801 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002802 goto error;
2803 }
2804
2805 /* check collision with mandatory/min-elements */
2806 if ((dev_target->flags & LYS_MAND_TRUE) ||
2807 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
fredganaa227c02019-11-09 11:27:56 +08002808 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
Michal Vasko53b7da02018-02-13 15:28:42 +01002809 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002810 "Adding the \"default\" statement is forbidden on %s statement.",
2811 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2812 goto error;
2813 }
2814 } else if (d->mod == LY_DEVIATE_RPL) {
2815 /* check that there was a value before */
2816 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2817 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
fredganaa227c02019-11-09 11:27:56 +08002818 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
Michal Vasko53b7da02018-02-13 15:28:42 +01002819 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002820 goto error;
2821 }
2822 }
2823
2824 if (dev_target->nodetype == LYS_LEAFLIST) {
2825 /* reallocate default list in the target */
2826 llist = (struct lys_node_leaflist *)dev_target;
2827 if (d->mod == LY_DEVIATE_ADD) {
2828 /* reallocate (enlarge) the unique array of the target */
2829 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002830 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002831 } else if (d->mod == LY_DEVIATE_RPL) {
2832 /* reallocate (replace) the unique array of the target */
2833 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002834 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002835 }
2836 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2837 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002838 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002839 }
2840 }
2841 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002842 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002843 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002844 if (c_ext) {
2845 /* some extensions may be already present from the substatements */
2846 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002847 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002848 d->ext = reallocated;
2849
2850 /* init memory */
2851 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2852 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002853
2854 /* process deviation properties with 0..n cardinality */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002855 deviate_must_index = 0;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002856 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2857 if (strcmp(child->ns->value, LY_NSYIN)) {
2858 /* extension */
2859 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2860 goto error;
2861 }
2862 d->ext_size++;
2863 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002864 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002865 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002866 goto error;
2867 }
2868
2869 /* find must to delete, we are ok with just matching conditions */
2870 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002871 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002872 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002873 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002874 /* ... and maintain the array */
2875 (*trg_must_size)--;
2876 if (i != *trg_must_size) {
2877 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2878 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2879 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2880 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2881 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2882 }
2883 if (!(*trg_must_size)) {
2884 free(*trg_must);
2885 *trg_must = NULL;
2886 } else {
2887 (*trg_must)[*trg_must_size].expr = NULL;
2888 (*trg_must)[*trg_must_size].dsc = NULL;
2889 (*trg_must)[*trg_must_size].ref = NULL;
2890 (*trg_must)[*trg_must_size].eapptag = NULL;
2891 (*trg_must)[*trg_must_size].emsg = NULL;
2892 }
2893
2894 i = -1; /* set match flag */
2895 break;
2896 }
2897 }
2898 d->must_size++;
2899 if (i != -1) {
2900 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002901 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002902 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002903 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002904 goto error;
2905 }
2906 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002907 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002908 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002909 goto error;
2910 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05002911 memcpy(d->must + deviate_must_index, &((*trg_must)[*trg_must_size]), sizeof *d->must);
2912 ++deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002913 (*trg_must_size)++;
2914 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002915
2916 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002917 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2918 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002919 goto error;
2920 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002921 } else if (!strcmp(child->name, "unique")) {
2922 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002923 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002924 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002925 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002926 goto error;
2927 }
2928
2929 /* find unique structures to delete */
2930 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002931 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002932 continue;
2933 }
2934
Radek Krejci581ce772015-11-10 17:22:40 +01002935 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002936 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002937 break;
2938 }
2939 }
2940
Radek Krejci581ce772015-11-10 17:22:40 +01002941 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002942 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002943 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002944 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002945 }
2946 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002947 /* ... and maintain the array */
2948 list->unique_size--;
2949 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002950 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2951 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002952 }
2953
2954 if (!list->unique_size) {
2955 free(list->unique);
2956 list->unique = NULL;
2957 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002958 list->unique[list->unique_size].expr_size = 0;
2959 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002960 }
2961
Radek Krejci6bd2c022017-02-01 15:04:49 +01002962 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002963 i = -1; /* set match flag */
2964 break;
2965 }
2966 }
2967
2968 d->unique_size++;
2969 if (i != -1) {
2970 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002971 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2972 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002973 goto error;
2974 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002975
2976 /* remove extensions of this unique instance from the target node */
2977 j = -1;
2978 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 +01002979 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002980 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2981 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002982 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002983 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002984 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002985 }
2986 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002987 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002988 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002989 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002990 list->unique_size++;
2991 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002992 goto error;
2993 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002994 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002995 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002996 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002997 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002998 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002999
3000 if (dev_target->nodetype == LYS_CHOICE) {
3001 choice = (struct lys_node_choice *)dev_target;
3002 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
3003 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003004 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003005 goto error;
3006 }
3007 if (d->mod == LY_DEVIATE_DEL) {
3008 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003009 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3010 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003011 goto error;
3012 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01003013 choice->dflt = NULL;
3014 /* remove extensions of this default instance from the target node */
3015 j = -1;
3016 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
3017 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3018 --j;
3019 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003020 } else { /* add or replace */
3021 choice->dflt = node;
3022 if (!choice->dflt) {
3023 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01003024 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003025 goto error;
3026 }
3027 }
3028 } else if (dev_target->nodetype == LYS_LEAF) {
3029 leaf = (struct lys_node_leaf *)dev_target;
3030 if (d->mod == LY_DEVIATE_DEL) {
3031 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003032 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3033 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003034 goto error;
3035 }
3036 /* remove value */
3037 lydict_remove(ctx, leaf->dflt);
3038 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01003039 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003040
3041 /* remove extensions of this default instance from the target node */
3042 j = -1;
3043 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
3044 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3045 --j;
3046 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003047 } else { /* add (already checked) and replace */
3048 /* remove value */
3049 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01003050 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003051
3052 /* set new value */
3053 leaf->dflt = lydict_insert(ctx, value, u);
3054
Radek Krejcibd117f02016-11-04 16:28:08 +01003055 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02003056 ly_set_add(dflt_check, dev_target, 0);
3057 }
3058 } else { /* LYS_LEAFLIST */
3059 llist = (struct lys_node_leaflist *)dev_target;
3060 if (d->mod == LY_DEVIATE_DEL) {
3061 /* find and remove the value in target list */
3062 for (i = 0; i < llist->dflt_size; i++) {
3063 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
3064 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01003065 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003066 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003067
3068 /* remove extensions of this default instance from the target node */
3069 j = -1;
3070 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 +01003071 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003072 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3073 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003074 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003075 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003076 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003077 }
3078 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003079 break;
3080 }
3081 }
3082 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003083 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3084 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 +02003085 goto error;
3086 }
3087 } else {
3088 /* add or replace, anyway we place items into the deviate's list
3089 which propagates to the target */
3090 /* we just want to check that the value isn't already in the list */
3091 for (i = 0; i < llist->dflt_size; i++) {
3092 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003093 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3094 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003095 goto error;
3096 }
3097 }
3098 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003099 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003100
3101 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3102 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003103 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003104 }
3105 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003106 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003107 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003108
3109 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3110 /* consolidate the final list in the target after removing items from it */
3111 llist = (struct lys_node_leaflist *)dev_target;
3112 for (i = j = 0; j < llist->dflt_size; j++) {
3113 llist->dflt[i] = llist->dflt[j];
3114 if (llist->dflt[i]) {
3115 i++;
3116 }
3117 }
3118 llist->dflt_size = i + 1;
3119 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003120 }
3121
Michal Vasko43a1feb2016-03-07 12:03:02 +01003122 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003123 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003124 for (u = 0; u < dflt_check->number; ++u) {
3125 value = NULL;
3126 rc = EXIT_SUCCESS;
3127 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3128 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3129 value = leaf->dflt;
3130 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3131 } else { /* LYS_LEAFLIST */
3132 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3133 for (j = 0; j < llist->dflt_size; j++) {
3134 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3135 (struct lys_node *)(&llist->dflt[j]));
3136 if (rc == -1) {
3137 value = llist->dflt[j];
3138 break;
3139 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003140 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003141
Michal Vasko15a43372017-09-25 14:12:42 +02003142 }
3143 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003144 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3145 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003146 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3147 dev->target_name);
3148 goto error;
3149 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003150 }
3151 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003152
Radek Krejci27fe55e2016-09-13 17:13:35 +02003153 /* mark all the affected modules as deviated and implemented */
3154 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3155 mod = lys_node_module(parent);
3156 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003157 mod->deviated = 1; /* main module */
3158 parent->module->deviated = 1; /* possible submodule */
Michal Vasko0f437062018-06-08 15:52:39 +02003159 if (!mod->implemented) {
3160 mod->implemented = 1;
3161 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
3162 goto error;
3163 }
Radek Krejci2bb5be72017-02-27 13:07:25 +01003164 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003165 }
3166 }
3167
Radek Krejcid5a5c282016-08-15 15:38:08 +02003168 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003169 return EXIT_SUCCESS;
3170
3171error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003172 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003173 return EXIT_FAILURE;
3174}
3175
Michal Vasko0d343d12015-08-24 14:57:36 +02003176/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003177static int
Radek Krejcib8048692015-08-05 13:36:34 +02003178fill_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 +01003179 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003180{
Michal Vasko53b7da02018-02-13 15:28:42 +01003181 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003183 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003184 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003185 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003186 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003187
Michal Vasko591e0b22015-08-13 13:53:43 +02003188 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003189 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003190 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003191 if (!aug->target_name) {
3192 goto error;
3193 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003195
Radek Krejci07d0fb92017-01-13 14:11:05 +01003196 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003197 goto error;
3198 }
3199
Radek Krejcie534c132016-11-23 13:32:31 +01003200 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3201 if (strcmp(sub->ns->value, LY_NSYIN)) {
3202 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003203 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003204 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003205 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003206 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003207 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003208 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003209 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003210 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003211 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003212 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003213 goto error;
3214 }
3215
Radek Krejci5323b492017-01-16 15:40:11 +01003216 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003217 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003218 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003219 goto error;
3220 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003221 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003222 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003223
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003224 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003225 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003226 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003227 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003228 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003229 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003230 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003231 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003232 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003233 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003234 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003235 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003236 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003237 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003238 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003239 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003240 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003241 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003242 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003243 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003244 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003245 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003246 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003247 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003248 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003249 goto error;
3250 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003251
Radek Krejci1d82ef62015-08-07 14:44:40 +02003252 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003253 goto error;
3254 }
3255
Radek Krejci1d82ef62015-08-07 14:44:40 +02003256 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003257 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003258 }
3259
Radek Krejcie534c132016-11-23 13:32:31 +01003260 if (c_ftrs) {
3261 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003262 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003263 }
Radek Krejcie534c132016-11-23 13:32:31 +01003264 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003265 /* some extensions may be already present from the substatements */
3266 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003267 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003268 aug->ext = reallocated;
3269
3270 /* init memory */
3271 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003272 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003273
Radek Krejcie534c132016-11-23 13:32:31 +01003274 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3275 if (strcmp(sub->ns->value, LY_NSYIN)) {
3276 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003277 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 +01003278 aug->ext_size++;
3279 if (ret) {
3280 goto error;
3281 }
3282 } else if (!strcmp(sub->name, "if-feature")) {
3283 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003284 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003285 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003286 goto error;
3287 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003288 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003289 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003290 }
3291
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003292 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003293 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003294 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003295 * when the uses does and cannot be resolved now for sure
3296 * (the grouping was not yet copied into uses).
3297 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003298 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003299 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003300 goto error;
3301 }
Michal Vasko49291b32015-08-06 09:49:41 +02003302 }
Radek Krejci106efc02015-06-10 14:36:27 +02003303
Michal Vasko508a50d2016-09-07 14:50:33 +02003304 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003305 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003306 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003307 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003308 goto error;
3309 }
3310 } else {
3311 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3312 goto error;
3313 }
3314 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003315 }
3316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003318
3319error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003321}
3322
Michal Vasko0d343d12015-08-24 14:57:36 +02003323/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003325fill_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 +02003326{
Michal Vasko53b7da02018-02-13 15:28:42 +01003327 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003328 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 struct lyxml_elem *sub, *next;
3330 const char *value;
3331 char *endptr;
3332 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003333 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 int r;
3335 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003336 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003337
Radek Krejci363bd4a2016-07-29 14:30:20 +02003338 assert(uses);
3339 module = uses->module; /* shorthand */
3340
Michal Vasko53b7da02018-02-13 15:28:42 +01003341 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003342 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003343 if (!rfn->target_name) {
3344 goto error;
3345 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003347 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003348 if (!sub->ns) {
3349 /* garbage */
3350 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003351 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003352 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003353 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003354 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003355
Radek Krejci411b1bf2017-01-23 16:40:05 +01003356 } else if (!strcmp(sub->name, "description")) {
3357 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003358 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003359 goto error;
3360 }
3361
Radek Krejci8d6b7422017-02-03 14:42:13 +01003362 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003363 goto error;
3364 }
3365
Michal Vasko53b7da02018-02-13 15:28:42 +01003366 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003367 if (!rfn->dsc) {
3368 goto error;
3369 }
3370 } else if (!strcmp(sub->name, "reference")) {
3371 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003372 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003373 goto error;
3374 }
3375
Radek Krejci8d6b7422017-02-03 14:42:13 +01003376 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003377 goto error;
3378 }
3379
Michal Vasko53b7da02018-02-13 15:28:42 +01003380 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003381 if (!rfn->ref) {
3382 goto error;
3383 }
3384 } else if (!strcmp(sub->name, "config")) {
3385 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003386 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003387 goto error;
3388 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003389 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003390 if (!strcmp(value, "false")) {
3391 rfn->flags |= LYS_CONFIG_R;
3392 } else if (!strcmp(value, "true")) {
3393 rfn->flags |= LYS_CONFIG_W;
3394 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003395 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003396 goto error;
3397 }
3398 rfn->flags |= LYS_CONFIG_SET;
3399
Radek Krejci8d6b7422017-02-03 14:42:13 +01003400 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003401 goto error;
3402 }
Radek Krejcie534c132016-11-23 13:32:31 +01003403 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003404 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 /* check possibility of statements combination */
3407 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003408 if (c_dflt) {
3409 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003410 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003411 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003412 goto error;
3413 }
Radek Krejci200bf712016-08-16 17:11:04 +02003414 rfn->target_type &= LYS_LEAFLIST;
3415 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003416 if (module->version < 2) {
3417 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3418 } else {
3419 /* YANG 1.1 */
3420 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3421 }
Radek Krejci200bf712016-08-16 17:11:04 +02003422 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003424 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3425 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 goto error;
3427 }
3428 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003429 if (module->version < 2) {
3430 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3431 } else {
3432 /* YANG 1.1 */
3433 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3434 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003436
Michal Vasko53b7da02018-02-13 15:28:42 +01003437 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003438 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 +01003439 goto error;
3440 }
Radek Krejci200bf712016-08-16 17:11:04 +02003441 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003442 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 } else if (!strcmp(sub->name, "mandatory")) {
3444 /* leaf, choice or anyxml */
3445 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003446 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 goto error;
3448 }
3449 /* just checking the flags in leaf is not sufficient, we would allow
3450 * multiple mandatory statements with the "false" value
3451 */
3452 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 /* check possibility of statements combination */
3455 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003456 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003458 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3459 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 goto error;
3461 }
3462 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003463 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003465
Michal Vasko53b7da02018-02-13 15:28:42 +01003466 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003468 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003470 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003472 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 goto error;
3474 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003475 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003476 goto error;
3477 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 } else if (!strcmp(sub->name, "min-elements")) {
3479 /* list or leaf-list */
3480 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003481 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 goto error;
3483 }
3484 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 /* check possibility of statements combination */
3487 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003488 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003490 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3491 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 goto error;
3493 }
3494 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003495 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003497
Michal Vasko53b7da02018-02-13 15:28:42 +01003498 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 while (isspace(value[0])) {
3500 value++;
3501 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003503 /* convert it to uint32_t */
3504 errno = 0;
3505 endptr = NULL;
3506 val = strtoul(value, &endptr, 10);
3507 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003508 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 goto error;
3510 }
3511 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003512 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003513
Radek Krejci8d6b7422017-02-03 14:42:13 +01003514 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003515 goto error;
3516 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 } else if (!strcmp(sub->name, "max-elements")) {
3518 /* list or leaf-list */
3519 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003520 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 goto error;
3522 }
3523 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 /* check possibility of statements combination */
3526 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003527 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003529 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3530 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 goto error;
3532 }
3533 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003534 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003536
Michal Vasko53b7da02018-02-13 15:28:42 +01003537 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 while (isspace(value[0])) {
3539 value++;
3540 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003541
Radek Krejci0d7b2472016-02-12 11:11:03 +01003542 if (!strcmp(value, "unbounded")) {
3543 rfn->mod.list.max = 0;
3544 } else {
3545 /* convert it to uint32_t */
3546 errno = 0;
3547 endptr = NULL;
3548 val = strtoul(value, &endptr, 10);
3549 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003550 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003551 goto error;
3552 }
3553 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003555 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003556
Radek Krejci8d6b7422017-02-03 14:42:13 +01003557 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003558 goto error;
3559 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 } else if (!strcmp(sub->name, "presence")) {
3561 /* container */
3562 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003563 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 goto error;
3565 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 /* check possibility of statements combination */
3568 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003569 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003571 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3572 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 goto error;
3574 }
3575 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003576 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003578
Michal Vasko53b7da02018-02-13 15:28:42 +01003579 GETVAL(ctx, value, sub, "value");
3580 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003581
Radek Krejci8d6b7422017-02-03 14:42:13 +01003582 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003583 goto error;
3584 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003585 } else if (!strcmp(sub->name, "must")) {
fredgan86754f92019-11-01 16:18:21 +08003586 /* leaf leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 /* 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 Krejci6e4ffbb2015-06-16 10:34:41 +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 Krejci6e4ffbb2015-06-16 10:34:41 +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 Krejci6e4ffbb2015-06-16 10:34:41 +02003597 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003598
Michal Vasko53b7da02018-02-13 15:28:42 +01003599 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003601 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003602
Radek Krejci363bd4a2016-07-29 14:30:20 +02003603 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
fredgan86754f92019-11-01 16:18:21 +08003604 /* leaf, leaf-list, list, container, choice, case, anydata or anyxml */
Radek Krejci363bd4a2016-07-29 14:30:20 +02003605 /* check possibility of statements combination */
3606 if (rfn->target_type) {
fredgan86754f92019-11-01 16:18:21 +08003607 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003608 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003609 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3610 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003611 goto error;
3612 }
3613 } else {
fredgan86754f92019-11-01 16:18:21 +08003614 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003615 }
3616
Michal Vasko53b7da02018-02-13 15:28:42 +01003617 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003618 c_ftrs++;
3619 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003620 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003621 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 goto error;
3623 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003624
Michal Vasko53b7da02018-02-13 15:28:42 +01003625 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 /* process nodes with cardinality of 0..n */
3629 if (c_must) {
3630 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003631 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003633 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003634 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003635 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 }
Radek Krejci200bf712016-08-16 17:11:04 +02003637 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003638 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003639 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003640 }
Radek Krejcie534c132016-11-23 13:32:31 +01003641 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003642 /* some extensions may be already present from the substatements */
3643 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003644 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003645 rfn->ext = reallocated;
3646
3647 /* init memory */
3648 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003649 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003650
Radek Krejcie534c132016-11-23 13:32:31 +01003651 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3652 if (strcmp(sub->ns->value, LY_NSYIN)) {
3653 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003654 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 +01003655 rfn->ext_size++;
3656 if (r) {
3657 goto error;
3658 }
3659 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003660 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003661 rfn->iffeature_size++;
3662 if (r) {
3663 goto error;
3664 }
Radek Krejci200bf712016-08-16 17:11:04 +02003665 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003666 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003667 rfn->must_size++;
3668 if (r) {
3669 goto error;
3670 }
Radek Krejci200bf712016-08-16 17:11:04 +02003671 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003672 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003673
3674 /* check for duplicity */
3675 for (r = 0; r < rfn->dflt_size; r++) {
3676 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003677 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3678 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003679 goto error;
3680 }
3681 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003682 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003683 }
3684 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003687
3688error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003689 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003690}
3691
Michal Vasko0d343d12015-08-24 14:57:36 +02003692/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693static int
Radek Krejcie534c132016-11-23 13:32:31 +01003694fill_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 +02003695{
Michal Vasko53b7da02018-02-13 15:28:42 +01003696 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003697 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003699 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003700 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003701
Radek Krejcie534c132016-11-23 13:32:31 +01003702 /* init */
3703 memset(&exts, 0, sizeof exts);
3704
3705 LY_TREE_FOR_SAFE(yin->child, next, child) {
3706 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003707 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003708 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003709 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3710 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003711 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003712 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003713 lyxml_unlink_elem(ctx, child, 2);
3714 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003715 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003716 GETVAL(ctx, value, child, "value");
3717 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 goto error;
3719 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003720 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003721
Radek Krejci8d6b7422017-02-03 14:42:13 +01003722 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003723 goto error;
3724 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 } else if (!strcmp(child->name, "revision-date")) {
3726 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003727 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003728 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003730 GETVAL(ctx, value, child, "date");
3731 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 goto error;
3733 }
3734 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003735
Radek Krejci8d6b7422017-02-03 14:42:13 +01003736 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003737 goto error;
3738 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003739 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003740 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003741 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003742 goto error;
3743 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003744 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003745 goto error;
3746 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003747 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003748 if (!imp->dsc) {
3749 goto error;
3750 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003751 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003752 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003753 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003754 goto error;
3755 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003756 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003757 goto error;
3758 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003759 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003760 if (!imp->ref) {
3761 goto error;
3762 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003764 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 goto error;
3766 }
3767 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 /* check mandatory information */
3770 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003771 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
3773 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003774
Radek Krejcie534c132016-11-23 13:32:31 +01003775 /* process extensions */
3776 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003777 /* some extensions may be already present from the substatements */
3778 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003779 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003780 imp->ext = reallocated;
3781
3782 /* init memory */
3783 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3784
Radek Krejcie534c132016-11-23 13:32:31 +01003785 LY_TREE_FOR_SAFE(exts.child, next, child) {
3786 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003787 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 +01003788 imp->ext_size++;
3789 if (r) {
3790 goto error;
3791 }
3792 }
3793 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003794
Michal Vasko53b7da02018-02-13 15:28:42 +01003795 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003796 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003797
3798error:
Radek Krejcie534c132016-11-23 13:32:31 +01003799 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003800 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003801 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003803}
3804
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003805/* logs directly
3806 * returns:
3807 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003808 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003809 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003811fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3812 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003813{
Michal Vasko53b7da02018-02-13 15:28:42 +01003814 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003815 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003817 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003818 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003819
Radek Krejcie534c132016-11-23 13:32:31 +01003820 /* init */
3821 memset(&exts, 0, sizeof exts);
3822
3823 LY_TREE_FOR_SAFE(yin->child, next, child) {
3824 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003825 /* garbage */
3826 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003827 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3828 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003829 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003830 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003831 lyxml_unlink_elem(ctx, child, 2);
3832 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003833 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003835 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 goto error;
3837 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003838 GETVAL(ctx, value, child, "date");
3839 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 goto error;
3841 }
3842 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003843
Radek Krejci8d6b7422017-02-03 14:42:13 +01003844 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003845 goto error;
3846 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003847 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003848 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003849 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003850 goto error;
3851 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003852 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003853 goto error;
3854 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003855 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003856 if (!inc->dsc) {
3857 goto error;
3858 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003859 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003860 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003861 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003862 goto error;
3863 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003864 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003865 goto error;
3866 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003867 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003868 if (!inc->ref) {
3869 goto error;
3870 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003872 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 goto error;
3874 }
3875 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003876
Radek Krejcie534c132016-11-23 13:32:31 +01003877 /* process extensions */
3878 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003879 /* some extensions may be already present from the substatements */
3880 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003881 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003882 inc->ext = reallocated;
3883
3884 /* init memory */
3885 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3886
Radek Krejcie534c132016-11-23 13:32:31 +01003887 LY_TREE_FOR_SAFE(exts.child, next, child) {
3888 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003889 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 +01003890 inc->ext_size++;
3891 if (r) {
3892 goto error;
3893 }
3894 }
3895 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003896
Michal Vasko53b7da02018-02-13 15:28:42 +01003897 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003898 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003899
3900error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003901 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003902}
3903
Michal Vasko0d343d12015-08-24 14:57:36 +02003904/* logs directly
3905 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003906 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003907 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003908 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003909 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003910static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003911read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3912 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003913{
Radek Krejcie4dce292017-10-30 11:16:47 +01003914 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 const char *value;
3916 struct lyxml_elem *sub, *next;
3917 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003918 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003920 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003921 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003925 GETVAL(ctx, value, xmlnode, "name");
3926 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003927 goto error;
3928 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003929 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 /* process local parameters */
3933 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003934 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003935 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003936 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003937 continue;
3938 }
3939 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003940 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003941 continue;
3942 }
3943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003945 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003946 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 goto error;
3948 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003949
Radek Krejci8d6b7422017-02-03 14:42:13 +01003950 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003951 goto error;
3952 }
3953
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 node->dsc = read_yin_subnode(ctx, sub, "text");
3955 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003956 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 }
3958 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003960 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 goto error;
3962 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003963
Radek Krejci8d6b7422017-02-03 14:42:13 +01003964 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003965 goto error;
3966 }
3967
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 node->ref = read_yin_subnode(ctx, sub, "text");
3969 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003970 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 }
3972 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003973 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003974 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 goto error;
3976 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003977 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003978 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003979 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003981 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003982 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003983 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003984 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003985 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003986 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003987 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003988
Radek Krejci8d6b7422017-02-03 14:42:13 +01003989 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003990 goto error;
3991 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003992 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3993 if (opt & OPT_CFG_PARSE) {
3994 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003995 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003996 goto error;
3997 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003998 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003999 if (!strcmp(value, "false")) {
4000 node->flags |= LYS_CONFIG_R;
4001 } else if (!strcmp(value, "true")) {
4002 node->flags |= LYS_CONFIG_W;
4003 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004004 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02004005 goto error;
4006 }
4007 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01004008
Radek Krejci8d6b7422017-02-03 14:42:13 +01004009 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01004010 goto error;
4011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004013 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01004014 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 continue;
4016 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004017 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004018 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004019
Michal Vaskoe022a562016-09-27 14:24:15 +02004020 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02004022 if (parent) {
4023 node->flags |= parent->flags & LYS_CONFIG_MASK;
4024 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004025 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004026 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 }
4028 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004029
Radek Krejci2cc25322017-09-06 16:32:02 +02004030 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
4031 /* status is not inherited by specification, but it not make sense to have
4032 * current in deprecated or deprecated in obsolete, so we print warning
4033 * and fix the schema by inheriting */
4034 if (!(node->flags & (LYS_STATUS_MASK))) {
4035 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01004036 if (stmt_type == LYEXT_PAR_NODE) {
4037 p = node->parent;
4038 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01004039 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004040 node->parent = p;
4041 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01004042 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004043 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004044 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
4045 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02004046 free(str);
4047 node->flags |= parent->flags & LYS_STATUS_MASK;
4048 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
4049 /* invalid combination of statuses */
4050 switch (node->flags & LYS_STATUS_MASK) {
4051 case 0:
4052 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01004053 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004054 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
4055 break;
4056 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01004057 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004058 "obsolete", parent->name);
4059 break;
4060 }
4061 goto error;
4062 }
4063 }
4064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004065 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004066
4067error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004068 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004069}
4070
Michal Vasko0d343d12015-08-24 14:57:36 +02004071/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004072static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004073read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004074{
Michal Vasko53b7da02018-02-13 15:28:42 +01004075 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004076 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004077 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004078 const char *value;
4079
4080 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004081 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004082
Michal Vasko53b7da02018-02-13 15:28:42 +01004083 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004084 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004085 if (!retval->cond) {
4086 goto error;
4087 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004088
Radek Krejci5323b492017-01-16 15:40:11 +01004089 LY_TREE_FOR_SAFE(yin->child, next, child) {
4090 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004091 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004092 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004093 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4094 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004095 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004096 goto error;
4097 }
4098 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004099 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004100 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004101 goto error;
4102 }
Radek Krejci5323b492017-01-16 15:40:11 +01004103
Radek Krejci8d6b7422017-02-03 14:42:13 +01004104 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004105 goto error;
4106 }
4107
Michal Vasko53b7da02018-02-13 15:28:42 +01004108 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004109 if (!retval->dsc) {
4110 goto error;
4111 }
4112 } else if (!strcmp(child->name, "reference")) {
4113 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004114 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004115 goto error;
4116 }
Radek Krejci5323b492017-01-16 15:40:11 +01004117
Radek Krejci8d6b7422017-02-03 14:42:13 +01004118 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004119 goto error;
4120 }
4121
Michal Vasko53b7da02018-02-13 15:28:42 +01004122 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004123 if (!retval->ref) {
4124 goto error;
4125 }
4126 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004127 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004128 goto error;
4129 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004130 }
4131
4132 return retval;
4133
4134error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004135 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004136 return NULL;
4137}
4138
Michal Vasko0d343d12015-08-24 14:57:36 +02004139/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004140static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004141read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004142 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004143{
Michal Vasko53b7da02018-02-13 15:28:42 +01004144 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004145 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004146 struct lys_node_case *cs;
4147 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004148 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004149 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004150
Radek Krejcie867c852015-08-27 09:52:34 +02004151 /* init */
4152 memset(&root, 0, sizeof root);
4153
Radek Krejci1d82ef62015-08-07 14:44:40 +02004154 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004155 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004156 cs->nodetype = LYS_CASE;
4157 cs->prev = (struct lys_node *)cs;
4158 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004159
Radek Krejci07d0fb92017-01-13 14:11:05 +01004160 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004161 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004162 goto error;
4163 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004164
Michal Vasko3e3228d2017-02-24 14:55:32 +01004165 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004166
Michal Vasko3a0043f2015-08-12 12:11:30 +02004167 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004168 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004169 goto error;
4170 }
4171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 /* process choice's specific children */
4173 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004174 if (strcmp(sub->ns->value, LY_NSYIN)) {
4175 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004176 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004177 c_ext++;
4178 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004179 !strcmp(sub->name, "leaf-list") ||
4180 !strcmp(sub->name, "leaf") ||
4181 !strcmp(sub->name, "list") ||
4182 !strcmp(sub->name, "uses") ||
4183 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004184 !strcmp(sub->name, "anyxml") ||
4185 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004186
Michal Vasko53b7da02018-02-13 15:28:42 +01004187 lyxml_unlink_elem(ctx, sub, 2);
4188 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004189 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004190 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004191 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004192 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004193 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004194 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004195 goto error;
4196 }
4197
Radek Krejci5323b492017-01-16 15:40:11 +01004198 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004199 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004200 goto error;
4201 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004202
Michal Vasko53b7da02018-02-13 15:28:42 +01004203 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004204 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004205 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004206 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004208 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004209
Radek Krejci3cf9e222015-06-18 11:37:50 +02004210 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004211 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004212 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004213 }
Radek Krejcie534c132016-11-23 13:32:31 +01004214 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004215 /* some extensions may be already present from the substatements */
4216 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004217 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004218 retval->ext = reallocated;
4219
4220 /* init memory */
4221 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004222 }
Radek Krejci21c81652017-01-23 10:42:55 +01004223
Radek Krejcie534c132016-11-23 13:32:31 +01004224 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4225 if (strcmp(sub->ns->value, LY_NSYIN)) {
4226 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004227 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 +01004228 retval->ext_size++;
4229 if (ret) {
4230 goto error;
4231 }
4232 } else {
4233 /* if-feature */
4234 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4235 cs->iffeature_size++;
4236 if (ret) {
4237 goto error;
4238 }
4239 }
4240 }
Radek Krejcib388c152015-06-04 17:03:03 +02004241
Michal Vasko29fc0182015-08-24 15:02:39 +02004242 /* last part - process data nodes */
4243 LY_TREE_FOR_SAFE(root.child, next, sub) {
4244 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004245 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004246 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004247 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004248 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004249 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004250 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004251 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004252 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004253 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004254 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004255 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004256 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004257 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004258 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004259 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004260 }
4261 if (!node) {
4262 goto error;
4263 }
4264
Michal Vasko53b7da02018-02-13 15:28:42 +01004265 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004266 }
4267
Michal Vasko508a50d2016-09-07 14:50:33 +02004268 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004269 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004270 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004271 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004272 goto error;
4273 }
4274 } else {
4275 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4276 goto error;
4277 }
4278 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004279 }
4280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004281 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004282
4283error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004284 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004285 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004286 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004287 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004290}
4291
Michal Vasko0d343d12015-08-24 14:57:36 +02004292/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004293static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004294read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004295 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004296{
Radek Krejci629cdef2016-06-06 15:06:36 +02004297 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004299 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004300 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004301 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004302 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004303 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004305 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004306 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004307
Radek Krejci76512572015-08-04 09:47:08 +02004308 choice->nodetype = LYS_CHOICE;
4309 choice->prev = (struct lys_node *)choice;
4310 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004311
Radek Krejci07d0fb92017-01-13 14:11:05 +01004312 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004313 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4314 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4315 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004316 goto error;
4317 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004318
Michal Vasko3e3228d2017-02-24 14:55:32 +01004319 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004320
Michal Vasko3a0043f2015-08-12 12:11:30 +02004321 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004322 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004323 goto error;
4324 }
4325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326 /* process choice's specific children */
4327 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004328 if (strcmp(sub->ns->value, LY_NSYIN)) {
4329 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004330 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004331 c_ext++;
4332 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004333 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004334 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004335 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004336 goto error;
4337 }
4338 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004339 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004340 goto error;
4341 }
4342 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004343 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 goto error;
4345 }
4346 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004347 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 goto error;
4349 }
4350 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004351 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 goto error;
4353 }
4354 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004355 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004356 goto error;
4357 }
4358 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004359 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 goto error;
4361 }
4362 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004363 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004364 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004365 goto error;
4366 }
Radek Krejci21c81652017-01-23 10:42:55 +01004367
Radek Krejci8d6b7422017-02-03 14:42:13 +01004368 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004369 goto error;
4370 }
4371
Radek Krejci629cdef2016-06-06 15:06:36 +02004372 dflt = sub;
4373 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004374 continue;
4375 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004377 } else if (!strcmp(sub->name, "mandatory")) {
4378 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004379 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 goto error;
4381 }
4382 /* just checking the flags in leaf is not sufficient, we would allow
4383 * multiple mandatory statements with the "false" value
4384 */
4385 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004386
Michal Vasko53b7da02018-02-13 15:28:42 +01004387 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004389 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004390 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004391 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004392 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004393 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004394 goto error;
4395 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004396
Radek Krejci8d6b7422017-02-03 14:42:13 +01004397 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004398 goto error;
4399 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004400 } else if (!strcmp(sub->name, "when")) {
4401 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004402 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004403 goto error;
4404 }
4405
Radek Krejci5323b492017-01-16 15:40:11 +01004406 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004407 if (!choice->when) {
4408 goto error;
4409 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004410 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004411 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004412 c_ftrs++;
4413
Michal Vasko345da0a2015-12-02 10:35:55 +01004414 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004415 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004416 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004417 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004418 goto error;
4419 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004421 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004424
Radek Krejci1d82ef62015-08-07 14:44:40 +02004425 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004426 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004428
Radek Krejci3cf9e222015-06-18 11:37:50 +02004429 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004430 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004431 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004432 }
Radek Krejcie534c132016-11-23 13:32:31 +01004433 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004434 /* some extensions may be already present from the substatements */
4435 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004436 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004437 retval->ext = reallocated;
4438
4439 /* init memory */
4440 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004441 }
4442
Radek Krejcie534c132016-11-23 13:32:31 +01004443 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4444 if (strcmp(sub->ns->value, LY_NSYIN)) {
4445 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004446 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 +01004447 retval->ext_size++;
4448 if (ret) {
4449 goto error;
4450 }
4451 } else {
4452 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4453 choice->iffeature_size++;
4454 if (ret) {
4455 goto error;
4456 }
4457 }
4458 }
4459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004461 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004462 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4463 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 goto error;
4465 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004468 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004469 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004470 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004471 goto error;
4472 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004473 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004475
Michal Vasko508a50d2016-09-07 14:50:33 +02004476 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004477 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004478 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004479 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004480 goto error;
4481 }
4482 } else {
4483 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4484 goto error;
4485 }
4486 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004487 }
4488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004490
4491error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004492 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004493 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004495}
4496
Michal Vasko0d343d12015-08-24 14:57:36 +02004497/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004498static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004499read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004500 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004501{
Michal Vasko53b7da02018-02-13 15:28:42 +01004502 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004503 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004504 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004505 struct lyxml_elem *sub, *next;
4506 const char *value;
4507 int r;
4508 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004509 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004510 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004513 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004514
Radek Krejcibf2abff2016-08-23 15:51:52 +02004515 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004516 anyxml->prev = (struct lys_node *)anyxml;
4517 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004518
Radek Krejci07d0fb92017-01-13 14:11:05 +01004519 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004520 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004521 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 goto error;
4523 }
Radek Krejci863c2852015-06-03 15:47:11 +02004524
Michal Vasko3e3228d2017-02-24 14:55:32 +01004525 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004526
Radek Krejcic189a952016-07-11 15:27:07 +02004527 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004528 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004529 goto error;
4530 }
4531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004533 if (strcmp(sub->ns->value, LY_NSYIN)) {
4534 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004535 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004536 c_ext++;
4537 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004539 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 goto error;
4541 }
4542 /* just checking the flags in leaf is not sufficient, we would allow
4543 * multiple mandatory statements with the "false" value
4544 */
4545 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004546
Michal Vasko53b7da02018-02-13 15:28:42 +01004547 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004548 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004549 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004550 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004551 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004552 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004553 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 goto error;
4555 }
4556 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004557
Radek Krejci8d6b7422017-02-03 14:42:13 +01004558 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004559 goto error;
4560 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004561 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004562 } else if (!strcmp(sub->name, "when")) {
4563 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004564 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004565 goto error;
4566 }
4567
Radek Krejci5323b492017-01-16 15:40:11 +01004568 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004569 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004570 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004571 goto error;
4572 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004573 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004575 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004577 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004578 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004579 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004582 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004583 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 }
4585 }
Radek Krejci863c2852015-06-03 15:47:11 +02004586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004587 /* middle part - process nodes with cardinality of 0..n */
4588 if (c_must) {
4589 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004590 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004592 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004593 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004594 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004595 }
Radek Krejcie534c132016-11-23 13:32:31 +01004596 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004597 /* some extensions may be already present from the substatements */
4598 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004599 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004600 retval->ext = reallocated;
4601
4602 /* init memory */
4603 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004604 }
Radek Krejci863c2852015-06-03 15:47:11 +02004605
Radek Krejcie534c132016-11-23 13:32:31 +01004606 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4607 if (strcmp(sub->ns->value, LY_NSYIN)) {
4608 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004609 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 +01004610 retval->ext_size++;
4611 if (r) {
4612 goto error;
4613 }
4614 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004615 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004616 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 if (r) {
4618 goto error;
4619 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004620 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004621 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004622 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004623 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004624 goto error;
4625 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004627 }
Radek Krejci863c2852015-06-03 15:47:11 +02004628
Michal Vasko508a50d2016-09-07 14:50:33 +02004629 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004630 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004631 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004632 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004633 goto error;
4634 }
4635 } else {
4636 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4637 goto error;
4638 }
4639 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004640 }
4641
PavolVican92f23622017-12-12 13:35:56 +01004642 for (r = 0; r < retval->ext_size; ++r) {
4643 /* set flag, which represent LYEXT_OPT_VALID */
4644 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004645 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004646 break;
4647 }
4648 }
4649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004651
4652error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004653 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004655}
4656
Michal Vasko0d343d12015-08-24 14:57:36 +02004657/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004658static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004659read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004660 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004661{
Michal Vasko53b7da02018-02-13 15:28:42 +01004662 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004663 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004664 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 struct lyxml_elem *sub, *next;
4666 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004667 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004668 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004669 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004672 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004673
Radek Krejci76512572015-08-04 09:47:08 +02004674 leaf->nodetype = LYS_LEAF;
4675 leaf->prev = (struct lys_node *)leaf;
4676 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004677
Radek Krejci07d0fb92017-01-13 14:11:05 +01004678 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004679 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4680 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4681 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 goto error;
4683 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004684
Michal Vasko3e3228d2017-02-24 14:55:32 +01004685 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004686
Radek Krejcic189a952016-07-11 15:27:07 +02004687 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004688 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004689 goto error;
4690 }
4691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004693 if (strcmp(sub->ns->value, LY_NSYIN)) {
4694 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004695 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004696 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004697 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004698 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004699 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004700 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004701 goto error;
4702 }
Michal Vasko88c29542015-11-27 14:57:53 +01004703 /* HACK for unres */
4704 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004705 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004706 /* postpone type resolution when if-feature parsing is done since we need
4707 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004708 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 } else if (!strcmp(sub->name, "default")) {
4710 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004711 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004712 goto error;
4713 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004714 GETVAL(ctx, value, sub, "value");
4715 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004716
Radek Krejci8d6b7422017-02-03 14:42:13 +01004717 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004718 goto error;
4719 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004720 } else if (!strcmp(sub->name, "units")) {
4721 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004722 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004723 goto error;
4724 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004725 GETVAL(ctx, value, sub, "name");
4726 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004727
Radek Krejci8d6b7422017-02-03 14:42:13 +01004728 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004729 goto error;
4730 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 } else if (!strcmp(sub->name, "mandatory")) {
4732 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004733 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 goto error;
4735 }
4736 /* just checking the flags in leaf is not sufficient, we would allow
4737 * multiple mandatory statements with the "false" value
4738 */
4739 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004740
Michal Vasko53b7da02018-02-13 15:28:42 +01004741 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004743 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004744 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004745 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004746 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004747 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 goto error;
4749 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004750
Radek Krejci8d6b7422017-02-03 14:42:13 +01004751 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004752 goto error;
4753 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004754 } else if (!strcmp(sub->name, "when")) {
4755 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004756 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004757 goto error;
4758 }
4759
Radek Krejci5323b492017-01-16 15:40:11 +01004760 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004761 if (!leaf->when) {
4762 goto error;
4763 }
4764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004766 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004767 c_must++;
4768 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004769 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004770 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004771 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004772 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004775 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004778
Michal Vasko88c29542015-11-27 14:57:53 +01004779 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004783 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004784 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004785 goto error;
4786 }
Michal Vasko478c4652016-07-21 12:55:01 +02004787 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004788 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4789 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004790 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4791 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004792 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004794 /* middle part - process nodes with cardinality of 0..n */
4795 if (c_must) {
4796 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004797 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004798 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004799 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004800 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004801 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004802 }
Radek Krejcie534c132016-11-23 13:32:31 +01004803 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004804 /* some extensions may be already present from the substatements */
4805 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004806 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004807 retval->ext = reallocated;
4808
4809 /* init memory */
4810 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004811 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004812
Radek Krejcie534c132016-11-23 13:32:31 +01004813 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4814 if (strcmp(sub->ns->value, LY_NSYIN)) {
4815 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004816 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 +01004817 retval->ext_size++;
4818 if (r) {
4819 goto error;
4820 }
4821 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004822 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004823 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 if (r) {
4825 goto error;
4826 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004827 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004828 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004829 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004830 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004831 goto error;
4832 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004834 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004835
Radek Krejcicbb473e2016-09-16 14:48:32 +02004836 /* finalize type parsing */
4837 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4838 leaf->type.der = NULL;
4839 goto error;
4840 }
4841
4842 /* check default value (if not defined, there still could be some restrictions
4843 * that need to be checked against a default value from a derived type) */
Michal Vasko6a057782018-03-09 13:24:33 +01004844 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004845 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4846 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004847 goto error;
4848 }
4849
Michal Vasko508a50d2016-09-07 14:50:33 +02004850 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004851 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004852 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004853 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004854 goto error;
4855 }
4856 } else {
4857 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4858 goto error;
4859 }
4860 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004861 }
4862
PavolVican92f23622017-12-12 13:35:56 +01004863 for (r = 0; r < retval->ext_size; ++r) {
4864 /* set flag, which represent LYEXT_OPT_VALID */
4865 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004866 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004867 break;
4868 }
4869 }
4870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004872
4873error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004874 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004876}
4877
Michal Vasko0d343d12015-08-24 14:57:36 +02004878/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004879static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004880read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004881 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004882{
Michal Vasko53b7da02018-02-13 15:28:42 +01004883 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004884 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004885 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004886 struct lyxml_elem *sub, *next;
4887 const char *value;
4888 char *endptr;
4889 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004890 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004891 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004892 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004893 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004895 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004896 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004897
Radek Krejci76512572015-08-04 09:47:08 +02004898 llist->nodetype = LYS_LEAFLIST;
4899 llist->prev = (struct lys_node *)llist;
4900 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004901
Radek Krejci07d0fb92017-01-13 14:11:05 +01004902 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004903 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4904 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4905 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 goto error;
4907 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004908
Michal Vasko3e3228d2017-02-24 14:55:32 +01004909 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004910
Radek Krejcic189a952016-07-11 15:27:07 +02004911 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004912 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004913 goto error;
4914 }
4915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004917 if (strcmp(sub->ns->value, LY_NSYIN)) {
4918 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004919 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004920 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004921 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004922 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004923 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004924 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004925 goto error;
4926 }
Michal Vasko88c29542015-11-27 14:57:53 +01004927 /* HACK for unres */
4928 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004929 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004930 /* postpone type resolution when if-feature parsing is done since we need
4931 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004932 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 } else if (!strcmp(sub->name, "units")) {
4934 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004935 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 goto error;
4937 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004938 GETVAL(ctx, value, sub, "name");
4939 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004940
Radek Krejci8d6b7422017-02-03 14:42:13 +01004941 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004942 goto error;
4943 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004944 } else if (!strcmp(sub->name, "ordered-by")) {
4945 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004946 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 goto error;
4948 }
4949 /* just checking the flags in llist is not sufficient, we would
4950 * allow multiple ordered-by statements with the "system" value
4951 */
4952 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004953
Radek Krejci1574a8d2015-08-03 14:16:52 +02004954 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4956 * state data
4957 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004958 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004959 continue;
4960 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004961
Michal Vasko53b7da02018-02-13 15:28:42 +01004962 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004963 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004964 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004965 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004966 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004968 } /* else system is the default value, so we can ignore it */
4969
Radek Krejci8d6b7422017-02-03 14:42:13 +01004970 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004971 goto error;
4972 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004973 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004974 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004975 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004976 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004977 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004978 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004979 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004980 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004981 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004982 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004983 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 +01004984 goto error;
4985 }
4986
Michal Vasko53b7da02018-02-13 15:28:42 +01004987 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004988 c_dflt++;
4989 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 } else if (!strcmp(sub->name, "min-elements")) {
4992 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004993 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004994 goto error;
4995 }
4996 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004997
Michal Vasko53b7da02018-02-13 15:28:42 +01004998 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999 while (isspace(value[0])) {
5000 value++;
5001 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 /* convert it to uint32_t */
5004 errno = 0;
5005 endptr = NULL;
5006 val = strtoul(value, &endptr, 10);
5007 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005008 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005009 goto error;
5010 }
5011 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005012 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005013 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5014 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005015 goto error;
5016 }
Radek Krejci5323b492017-01-16 15:40:11 +01005017
Radek Krejci8d6b7422017-02-03 14:42:13 +01005018 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005019 goto error;
5020 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 } else if (!strcmp(sub->name, "max-elements")) {
5022 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005023 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005024 goto error;
5025 }
5026 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005027
Michal Vasko53b7da02018-02-13 15:28:42 +01005028 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005029 while (isspace(value[0])) {
5030 value++;
5031 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005032
Radek Krejci0d7b2472016-02-12 11:11:03 +01005033 if (!strcmp(value, "unbounded")) {
5034 llist->max = 0;
5035 } else {
5036 /* convert it to uint32_t */
5037 errno = 0;
5038 endptr = NULL;
5039 val = strtoul(value, &endptr, 10);
5040 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005041 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005042 goto error;
5043 }
5044 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005045 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005046 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5047 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005048 goto error;
5049 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 }
Radek Krejci5323b492017-01-16 15:40:11 +01005051
Radek Krejci8d6b7422017-02-03 14:42:13 +01005052 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005053 goto error;
5054 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005055 } else if (!strcmp(sub->name, "when")) {
5056 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005057 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005058 goto error;
5059 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005060
Radek Krejci5323b492017-01-16 15:40:11 +01005061 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005062 if (!llist->when) {
5063 goto error;
5064 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005066 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005067 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005068 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005069
Michal Vasko88c29542015-11-27 14:57:53 +01005070 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005071 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005073 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005074 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005075 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005076 goto error;
5077 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005079 /* middle part - process nodes with cardinality of 0..n */
5080 if (c_must) {
5081 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005082 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005083 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005084 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005085 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005086 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005087 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005088 if (c_dflt) {
5089 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005090 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005091 }
Radek Krejcie534c132016-11-23 13:32:31 +01005092 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005093 /* some extensions may be already present from the substatements */
5094 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005095 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005096 retval->ext = reallocated;
5097
5098 /* init memory */
5099 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005100 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005101
Radek Krejcie534c132016-11-23 13:32:31 +01005102 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5103 if (strcmp(sub->ns->value, LY_NSYIN)) {
5104 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005105 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 +01005106 retval->ext_size++;
5107 if (r) {
5108 goto error;
5109 }
5110 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005111 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005112 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005113 if (r) {
5114 goto error;
5115 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005116 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005117 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005118 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005119 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005120 goto error;
5121 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005122 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005123 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005124
Radek Krejciac1a52c2016-09-15 14:42:40 +02005125 /* check for duplicity in case of configuration data,
5126 * in case of status data duplicities are allowed */
5127 if (llist->flags & LYS_CONFIG_W) {
5128 for (r = 0; r < llist->dflt_size; r++) {
5129 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005130 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5131 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005132 goto error;
5133 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005134 }
5135 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005136 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005139
Radek Krejcicbb473e2016-09-16 14:48:32 +02005140 /* finalize type parsing */
5141 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5142 llist->type.der = NULL;
5143 goto error;
5144 }
5145
Radek Krejcid5a5c282016-08-15 15:38:08 +02005146 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005147 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5148 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005149 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5150 goto error;
5151 }
5152
5153 /* check default value (if not defined, there still could be some restrictions
5154 * that need to be checked against a default value from a derived type) */
5155 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko6a057782018-03-09 13:24:33 +01005156 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005157 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5158 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005159 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005160 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005161 }
5162
Michal Vasko508a50d2016-09-07 14:50:33 +02005163 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005164 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005165 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005166 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005167 goto error;
5168 }
5169 } else {
5170 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5171 goto error;
5172 }
5173 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005174 }
5175
PavolVican92f23622017-12-12 13:35:56 +01005176 for (r = 0; r < retval->ext_size; ++r) {
5177 /* set flag, which represent LYEXT_OPT_VALID */
5178 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005179 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005180 break;
5181 }
5182 }
5183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005184 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005185
5186error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005187 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005189}
5190
Michal Vasko0d343d12015-08-24 14:57:36 +02005191/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005192static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005193read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005194 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005195{
Michal Vasko53b7da02018-02-13 15:28:42 +01005196 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005197 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005198 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005199 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005200 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005201 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005202 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005203 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 char *auxs;
5205 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005206 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 /* init */
5209 memset(&root, 0, sizeof root);
5210 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005212 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005213 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005214
Radek Krejci76512572015-08-04 09:47:08 +02005215 list->nodetype = LYS_LIST;
5216 list->prev = (struct lys_node *)list;
5217 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005218
Radek Krejci07d0fb92017-01-13 14:11:05 +01005219 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005220 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5221 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5222 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 goto error;
5224 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005225
Michal Vasko3e3228d2017-02-24 14:55:32 +01005226 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005227
Radek Krejcic189a952016-07-11 15:27:07 +02005228 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005229 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005230 goto error;
5231 }
5232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 /* process list's specific children */
5234 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005235 if (strcmp(sub->ns->value, LY_NSYIN)) {
5236 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005237 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005238 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005239 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005241 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005242 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243 !strcmp(sub->name, "leaf-list") ||
5244 !strcmp(sub->name, "leaf") ||
5245 !strcmp(sub->name, "list") ||
5246 !strcmp(sub->name, "choice") ||
5247 !strcmp(sub->name, "uses") ||
5248 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005249 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005250 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005251 !strcmp(sub->name, "action") ||
5252 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005253 lyxml_unlink_elem(ctx, sub, 2);
5254 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005256 /* array counters */
5257 } else if (!strcmp(sub->name, "key")) {
5258 /* check cardinality 0..1 */
5259 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005260 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 goto error;
5262 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005265 GETVAL(ctx, value, sub, "value");
5266 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005267 while ((value = strpbrk(value, " \t\n"))) {
5268 list->keys_size++;
5269 while (isspace(*value)) {
5270 value++;
5271 }
5272 }
5273 list->keys_size++;
5274 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005275 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005276
Radek Krejci8d6b7422017-02-03 14:42:13 +01005277 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005278 goto error;
5279 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005280 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005282 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005283 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005284 lyxml_unlink_elem(ctx, sub, 2);
5285 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005287 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005288 c_tpdf++;
5289 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005290 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005291 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005292 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005293 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005294 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 /* optional stetments */
5297 } else if (!strcmp(sub->name, "ordered-by")) {
5298 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005299 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 goto error;
5301 }
5302 /* just checking the flags in llist is not sufficient, we would
5303 * allow multiple ordered-by statements with the "system" value
5304 */
5305 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005306
Radek Krejci1574a8d2015-08-03 14:16:52 +02005307 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5309 * state data
5310 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005311 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 continue;
5313 }
Radek Krejci345ad742015-06-03 11:04:18 +02005314
Michal Vasko53b7da02018-02-13 15:28:42 +01005315 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005317 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005319 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005320 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005321 } /* else system is the default value, so we can ignore it */
5322
Radek Krejci8d6b7422017-02-03 14:42:13 +01005323 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005324 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005325 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005326 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005327 } else if (!strcmp(sub->name, "min-elements")) {
5328 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005329 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005330 goto error;
5331 }
5332 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005333
Michal Vasko53b7da02018-02-13 15:28:42 +01005334 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005335 while (isspace(value[0])) {
5336 value++;
5337 }
Radek Krejci345ad742015-06-03 11:04:18 +02005338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005339 /* convert it to uint32_t */
5340 errno = 0;
5341 auxs = NULL;
5342 val = strtoul(value, &auxs, 10);
5343 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005344 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005345 goto error;
5346 }
5347 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005348 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005349 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5350 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5351 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005352 goto error;
5353 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005354 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005355 goto error;
5356 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005357 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005358 } else if (!strcmp(sub->name, "max-elements")) {
5359 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005360 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005361 goto error;
5362 }
5363 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005364
Michal Vasko53b7da02018-02-13 15:28:42 +01005365 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 while (isspace(value[0])) {
5367 value++;
5368 }
Radek Krejci345ad742015-06-03 11:04:18 +02005369
Radek Krejci0d7b2472016-02-12 11:11:03 +01005370 if (!strcmp(value, "unbounded")) {
5371 list->max = 0;;
5372 } else {
5373 /* convert it to uint32_t */
5374 errno = 0;
5375 auxs = NULL;
5376 val = strtoul(value, &auxs, 10);
5377 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005378 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005379 goto error;
5380 }
5381 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005382 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005383 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5384 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005385 goto error;
5386 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005387 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005388 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005389 goto error;
5390 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005391 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005392 } else if (!strcmp(sub->name, "when")) {
5393 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005394 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005395 goto error;
5396 }
5397
Radek Krejci5323b492017-01-16 15:40:11 +01005398 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005399 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005400 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005401 goto error;
5402 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005403 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005404 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005405 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005406 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005407 }
5408 }
Radek Krejci345ad742015-06-03 11:04:18 +02005409
Michal Vaskoe022a562016-09-27 14:24:15 +02005410 /* check - if list is configuration, key statement is mandatory
5411 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005412 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005413 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005414 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005415 goto error;
5416 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005418 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5419 if (c_tpdf) {
5420 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005421 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005422 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005423 if (c_must) {
5424 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005425 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005426 }
5427 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005428 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005429 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005430 }
Radek Krejcie534c132016-11-23 13:32:31 +01005431 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005432 /* some extensions may be already present from the substatements */
5433 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005434 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005435 retval->ext = reallocated;
5436
5437 /* init memory */
5438 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005439 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005440
Radek Krejcie534c132016-11-23 13:32:31 +01005441 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5442 if (strcmp(sub->ns->value, LY_NSYIN)) {
5443 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005444 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 +01005445 retval->ext_size++;
5446 if (r) {
5447 goto error;
5448 }
5449 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005450 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5451 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005452 if (r) {
5453 goto error;
5454 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005455 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005456 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005457 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005458 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005459 goto error;
5460 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005461 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005462 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005463 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005464 if (r) {
5465 goto error;
5466 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005467 }
5468 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005470 /* last part - process data nodes */
5471 LY_TREE_FOR_SAFE(root.child, next, sub) {
5472 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005473 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005474 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005475 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005477 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005478 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005479 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005480 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005481 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005482 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005483 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005484 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005485 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005486 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005487 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005488 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005489 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005490 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005491 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005492 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005493 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005494 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005495 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005496 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005497 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005498 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005499 goto error;
5500 }
Radek Krejci73adb602015-07-02 18:07:40 +02005501
Michal Vasko53b7da02018-02-13 15:28:42 +01005502 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005503 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005504
Radek Krejci5c08a992016-11-02 13:30:04 +01005505 if (list->keys_str) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02005506 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005507 goto error;
5508 }
5509 } /* 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 +02005510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005511 /* process unique statements */
5512 if (c_uniq) {
5513 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005514 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005515
Radek Krejci461efb92016-02-12 15:52:18 +01005516 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5517 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5518 list->unique_size++;
5519 if (r) {
5520 goto error;
5521 }
5522
Radek Krejci8d6b7422017-02-03 14:42:13 +01005523 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005524 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5525 goto error;
5526 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005527 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005528 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005530
Michal Vasko508a50d2016-09-07 14:50:33 +02005531 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005532 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005533 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005534 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005535 goto error;
5536 }
5537 } else {
5538 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5539 goto error;
5540 }
5541 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005542 }
5543
PavolVican92f23622017-12-12 13:35:56 +01005544 for (r = 0; r < retval->ext_size; ++r) {
5545 /* set flag, which represent LYEXT_OPT_VALID */
5546 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005547 retval->flags |= LYS_VALID_EXT;
Robin Jarry8d820d32019-04-06 12:26:13 +02005548 if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
5549 retval->flags |= LYS_VALID_EXT_SUBTREE;
5550 break;
5551 }
PavolVican92f23622017-12-12 13:35:56 +01005552 }
5553 }
5554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005555 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005556
5557error:
5558
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005559 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005560 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005561 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 }
5563 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005564 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005565 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005567 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005568}
5569
Michal Vasko0d343d12015-08-24 14:57:36 +02005570/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005571static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005572read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005573 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005574{
Michal Vasko53b7da02018-02-13 15:28:42 +01005575 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005576 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005577 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005578 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005579 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005580 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005581 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005582 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005583 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005585 /* init */
5586 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005588 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005589 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005590
Radek Krejci76512572015-08-04 09:47:08 +02005591 cont->nodetype = LYS_CONTAINER;
5592 cont->prev = (struct lys_node *)cont;
5593 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005594
Radek Krejci07d0fb92017-01-13 14:11:05 +01005595 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005596 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5597 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5598 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005599 goto error;
5600 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005601
Michal Vasko3e3228d2017-02-24 14:55:32 +01005602 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005603
Radek Krejcic189a952016-07-11 15:27:07 +02005604 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005605 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005606 goto error;
5607 }
5608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005609 /* process container's specific children */
5610 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005611 if (strcmp(sub->ns->value, LY_NSYIN)) {
5612 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005613 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005614 c_ext++;
5615 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005616 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005617 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005618 goto error;
5619 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005620 GETVAL(ctx, value, sub, "value");
5621 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005622
Radek Krejci8d6b7422017-02-03 14:42:13 +01005623 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005624 goto error;
5625 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005626 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005627 } else if (!strcmp(sub->name, "when")) {
5628 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005629 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005630 goto error;
5631 }
5632
Radek Krejci5323b492017-01-16 15:40:11 +01005633 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005634 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005635 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005636 goto error;
5637 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005638 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005640 /* data statements */
5641 } else if (!strcmp(sub->name, "container") ||
5642 !strcmp(sub->name, "leaf-list") ||
5643 !strcmp(sub->name, "leaf") ||
5644 !strcmp(sub->name, "list") ||
5645 !strcmp(sub->name, "choice") ||
5646 !strcmp(sub->name, "uses") ||
5647 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005648 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005649 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005650 !strcmp(sub->name, "action") ||
5651 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005652 lyxml_unlink_elem(ctx, sub, 2);
5653 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005655 /* array counters */
5656 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005657 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005658 c_tpdf++;
5659 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005660 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005661 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005662 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005663 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005664 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005665 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005666 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005667 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005668 }
5669 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005671 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5672 if (c_tpdf) {
5673 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005674 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005675 }
5676 if (c_must) {
5677 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005678 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005679 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005680 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005681 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005682 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005683 }
Radek Krejcie534c132016-11-23 13:32:31 +01005684 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005685 /* some extensions may be already present from the substatements */
5686 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005687 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005688 retval->ext = reallocated;
5689
5690 /* init memory */
5691 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005692 }
Radek Krejci800af702015-06-02 13:46:01 +02005693
Radek Krejcie534c132016-11-23 13:32:31 +01005694 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5695 if (strcmp(sub->ns->value, LY_NSYIN)) {
5696 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005697 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 +01005698 retval->ext_size++;
5699 if (r) {
5700 goto error;
5701 }
5702 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005703 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5704 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005705 if (r) {
5706 goto error;
5707 }
5708 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005709 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005710 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005711 if (r) {
5712 goto error;
5713 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005714 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005715 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005716 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005717 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005718 goto error;
5719 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005720 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005721 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005723 /* last part - process data nodes */
5724 LY_TREE_FOR_SAFE(root.child, next, sub) {
5725 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005726 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005727 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005728 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005730 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005731 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005732 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005733 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005734 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005735 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005736 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005737 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005738 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005739 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005740 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005741 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005742 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005743 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005744 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005745 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005746 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005747 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005748 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749 goto error;
5750 }
Radek Krejci73adb602015-07-02 18:07:40 +02005751
Michal Vasko53b7da02018-02-13 15:28:42 +01005752 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005753 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005754
Michal Vasko508a50d2016-09-07 14:50:33 +02005755 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005756 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005757 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005758 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005759 goto error;
5760 }
5761 } else {
5762 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5763 goto error;
5764 }
5765 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005766 }
5767
PavolVican92f23622017-12-12 13:35:56 +01005768 for (r = 0; r < retval->ext_size; ++r) {
5769 /* set flag, which represent LYEXT_OPT_VALID */
5770 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005771 retval->flags |= LYS_VALID_EXT;
Robin Jarry8d820d32019-04-06 12:26:13 +02005772 if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
5773 retval->flags |= LYS_VALID_EXT_SUBTREE;
5774 break;
5775 }
PavolVican92f23622017-12-12 13:35:56 +01005776 }
5777 }
5778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005779 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005780
5781error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005782 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005783 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005784 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005785 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005786 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005787}
5788
Michal Vasko0d343d12015-08-24 14:57:36 +02005789/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005790static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005791read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005792 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005793{
Michal Vasko53b7da02018-02-13 15:28:42 +01005794 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005795 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005796 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005797 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005798 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005799 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005800 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005801 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005803 /* init */
5804 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005806 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005807 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005808
Radek Krejci76512572015-08-04 09:47:08 +02005809 grp->nodetype = LYS_GROUPING;
5810 grp->prev = (struct lys_node *)grp;
5811 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005812
Radek Krejci07d0fb92017-01-13 14:11:05 +01005813 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005814 goto error;
5815 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005816
Michal Vasko3e3228d2017-02-24 14:55:32 +01005817 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005818
Radek Krejcic189a952016-07-11 15:27:07 +02005819 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005820 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005821 goto error;
5822 }
5823
Radek Krejci1d82ef62015-08-07 14:44:40 +02005824 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005825 if (strcmp(sub->ns->value, LY_NSYIN)) {
5826 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005827 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005828 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005830 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005831 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005832 !strcmp(sub->name, "leaf-list") ||
5833 !strcmp(sub->name, "leaf") ||
5834 !strcmp(sub->name, "list") ||
5835 !strcmp(sub->name, "choice") ||
5836 !strcmp(sub->name, "uses") ||
5837 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005838 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005839 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005840 !strcmp(sub->name, "action") ||
5841 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005842 lyxml_unlink_elem(ctx, sub, 2);
5843 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005845 /* array counters */
5846 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005847 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005848 c_tpdf++;
5849 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005850 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005851 goto error;
5852 }
5853 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005855 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5856 if (c_tpdf) {
5857 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005858 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005859 }
Radek Krejcie534c132016-11-23 13:32:31 +01005860 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005861 /* some extensions may be already present from the substatements */
5862 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005863 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005864 retval->ext = reallocated;
5865
5866 /* init memory */
5867 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005868 }
Radek Krejcie534c132016-11-23 13:32:31 +01005869 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5870 if (strcmp(sub->ns->value, LY_NSYIN)) {
5871 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005872 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 +01005873 retval->ext_size++;
5874 if (r) {
5875 goto error;
5876 }
5877 } else {
5878 /* typedef */
5879 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5880 grp->tpdf_size++;
5881 if (r) {
5882 goto error;
5883 }
5884 }
5885 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005887 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005888 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005889 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005890 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005891 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005892 LY_TREE_FOR_SAFE(root.child, next, sub) {
5893 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005894 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005895 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005896 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005897 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005898 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005899 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005900 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005901 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005902 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005903 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005904 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005905 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005906 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005907 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005908 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005909 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005910 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005911 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005912 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005913 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005914 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005915 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005916 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005917 goto error;
5918 }
Radek Krejci73adb602015-07-02 18:07:40 +02005919
Michal Vasko53b7da02018-02-13 15:28:42 +01005920 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005921 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005923 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005924
5925error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005926 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005927 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005928 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005929 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005930 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005931}
5932
Michal Vasko0d343d12015-08-24 14:57:36 +02005933/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005934static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005935read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005936 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005937{
Michal Vasko53b7da02018-02-13 15:28:42 +01005938 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005939 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005940 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005941 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005942 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005943 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005944 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005945
Radek Krejcie0674f82015-06-15 13:58:51 +02005946 /* init */
5947 memset(&root, 0, sizeof root);
5948
Michal Vasko38d01f72015-06-15 09:41:06 +02005949 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005950 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005951 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005952
5953 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005954 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005955 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005956 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005957 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005958 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005959 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005960 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005961 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005962 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005963 }
5964
Radek Krejci76512572015-08-04 09:47:08 +02005965 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005966 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005967
Michal Vasko3e3228d2017-02-24 14:55:32 +01005968 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005969
Radek Krejcic189a952016-07-11 15:27:07 +02005970 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005971 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005972 goto error;
5973 }
5974
Michal Vasko38d01f72015-06-15 09:41:06 +02005975 /* data statements */
5976 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005977 if (!sub->ns) {
5978 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005979 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005980 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005981 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005982 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005983 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005984 c_ext++;
5985 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005986 !strcmp(sub->name, "leaf-list") ||
5987 !strcmp(sub->name, "leaf") ||
5988 !strcmp(sub->name, "list") ||
5989 !strcmp(sub->name, "choice") ||
5990 !strcmp(sub->name, "uses") ||
5991 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005992 !strcmp(sub->name, "anyxml") ||
5993 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005994 lyxml_unlink_elem(ctx, sub, 2);
5995 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005997 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005998 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005999 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006000 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006001 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02006002
Radek Krejci1a31efe2016-07-29 11:04:16 +02006003 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006004 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02006005 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02006006 c_must++;
6007
Michal Vasko38d01f72015-06-15 09:41:06 +02006008 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006009 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006010 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006011 }
6012 }
6013
Michal Vaskob04e5a82020-01-03 15:54:36 +01006014 if (!root.child) {
6015 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "schema-node", strnodetype(retval->nodetype));
6016 goto error;
6017 }
6018
Michal Vasko38d01f72015-06-15 09:41:06 +02006019 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6020 if (c_tpdf) {
6021 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006022 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006023 }
Radek Krejci19332802016-07-29 10:39:46 +02006024 if (c_must) {
6025 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006026 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02006027 }
Radek Krejcie534c132016-11-23 13:32:31 +01006028 if (c_ext) {
6029 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006030 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01006031 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006032
Radek Krejcie534c132016-11-23 13:32:31 +01006033 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6034 if (strcmp(sub->ns->value, LY_NSYIN)) {
6035 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006036 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 +01006037 retval->ext_size++;
6038 if (r) {
6039 goto error;
6040 }
6041 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006042 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006043 inout->must_size++;
6044 if (r) {
6045 goto error;
6046 }
6047 } else { /* typedef */
6048 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
6049 inout->tpdf_size++;
6050 if (r) {
6051 goto error;
6052 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006053 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006054 }
6055
6056 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006057 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02006058 LY_TREE_FOR_SAFE(root.child, next, sub) {
6059 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006060 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006061 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006062 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006063 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006064 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006065 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006066 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006067 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006068 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006069 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006070 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006071 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006072 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006073 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006074 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006075 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006076 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006077 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006078 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006079 goto error;
6080 }
Radek Krejci73adb602015-07-02 18:07:40 +02006081
Michal Vasko53b7da02018-02-13 15:28:42 +01006082 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006083 }
6084
Michal Vasko508a50d2016-09-07 14:50:33 +02006085 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006086 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006087 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006088 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006089 goto error;
6090 }
6091 } else {
6092 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6093 goto error;
6094 }
6095 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006096 }
6097
Michal Vasko38d01f72015-06-15 09:41:06 +02006098 return retval;
6099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006100error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006101 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006102 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006103 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006104 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006105 return NULL;
6106}
6107
Michal Vasko0d343d12015-08-24 14:57:36 +02006108/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006109static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006110read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006111 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006112{
Michal Vasko53b7da02018-02-13 15:28:42 +01006113 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006114 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006115 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006116 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006117 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006118 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006119 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006120 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006121
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006122 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006123 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006124 return NULL;
6125 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006126
Michal Vaskoc6551b32015-06-16 10:51:43 +02006127 memset(&root, 0, sizeof root);
6128
Michal Vasko0ea41032015-06-16 08:53:55 +02006129 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006130 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006131
Radek Krejci76512572015-08-04 09:47:08 +02006132 notif->nodetype = LYS_NOTIF;
6133 notif->prev = (struct lys_node *)notif;
6134 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006135
Radek Krejci07d0fb92017-01-13 14:11:05 +01006136 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006137 goto error;
6138 }
6139
Michal Vasko3e3228d2017-02-24 14:55:32 +01006140 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006141
Radek Krejcic189a952016-07-11 15:27:07 +02006142 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006143 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006144 goto error;
6145 }
6146
Michal Vasko0ea41032015-06-16 08:53:55 +02006147 /* process rpc's specific children */
6148 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006149 if (strcmp(sub->ns->value, LY_NSYIN)) {
6150 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006151 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006152 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006153 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006154
Michal Vasko0ea41032015-06-16 08:53:55 +02006155 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006156 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006157 !strcmp(sub->name, "leaf-list") ||
6158 !strcmp(sub->name, "leaf") ||
6159 !strcmp(sub->name, "list") ||
6160 !strcmp(sub->name, "choice") ||
6161 !strcmp(sub->name, "uses") ||
6162 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006163 !strcmp(sub->name, "anyxml") ||
6164 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006165 lyxml_unlink_elem(ctx, sub, 2);
6166 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006168 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006169 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006170 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006171 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006172 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006173 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006174 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006175 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006176 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006177 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006178 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006179 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006180 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006181 }
6182 }
6183
6184 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6185 if (c_tpdf) {
6186 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006187 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006188 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006189 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006190 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006191 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006192 }
Radek Krejci19332802016-07-29 10:39:46 +02006193 if (c_must) {
6194 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006195 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006196 }
Radek Krejcie534c132016-11-23 13:32:31 +01006197 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006198 /* some extensions may be already present from the substatements */
6199 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006200 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006201 retval->ext = reallocated;
6202
6203 /* init memory */
6204 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006205 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006206
Radek Krejcie534c132016-11-23 13:32:31 +01006207 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6208 if (strcmp(sub->ns->value, LY_NSYIN)) {
6209 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006210 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 +01006211 retval->ext_size++;
6212 if (r) {
6213 goto error;
6214 }
6215 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006216 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6217 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006218 if (r) {
6219 goto error;
6220 }
Radek Krejci96299152016-06-22 10:17:50 +02006221 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006222 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006223 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006224 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006225 goto error;
6226 }
Radek Krejci19332802016-07-29 10:39:46 +02006227 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006228 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006229 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006230 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006231 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006232 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006233 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006234 }
6235
6236 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006237 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006238 LY_TREE_FOR_SAFE(root.child, next, sub) {
6239 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006240 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006241 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006242 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006243 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006244 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006245 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006246 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006247 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006248 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006249 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006250 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006251 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006252 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006253 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006254 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006255 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006256 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006257 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006258 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006259 goto error;
6260 }
Radek Krejci73adb602015-07-02 18:07:40 +02006261
Michal Vasko53b7da02018-02-13 15:28:42 +01006262 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006263 }
6264
Michal Vasko508a50d2016-09-07 14:50:33 +02006265 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006266 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006267 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006268 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006269 goto error;
6270 }
6271 } else {
6272 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6273 goto error;
6274 }
6275 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006276 }
6277
Michal Vasko0ea41032015-06-16 08:53:55 +02006278 return retval;
6279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006280error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006281 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006282 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006283 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006284 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006285 return NULL;
6286}
6287
Michal Vasko0d343d12015-08-24 14:57:36 +02006288/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006289static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006290read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006291 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006292{
Michal Vasko53b7da02018-02-13 15:28:42 +01006293 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006294 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006295 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006296 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006297 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006298 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006299 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006300 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006301
Michal Vasko8fa6ec22020-03-05 15:29:26 +01006302 if (!strcmp(yin->name, "action") && (module->version < 2)) {
6303 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
6304 return NULL;
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006305 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006306
Radek Krejcie0674f82015-06-15 13:58:51 +02006307 /* init */
6308 memset(&root, 0, sizeof root);
6309
Michal Vasko38d01f72015-06-15 09:41:06 +02006310 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006311 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006312
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006313 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006314 rpc->prev = (struct lys_node *)rpc;
6315 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006316
Radek Krejci07d0fb92017-01-13 14:11:05 +01006317 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006318 goto error;
6319 }
6320
Michal Vasko3e3228d2017-02-24 14:55:32 +01006321 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006322
Radek Krejcic189a952016-07-11 15:27:07 +02006323 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006324 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006325 goto error;
6326 }
6327
Michal Vasko38d01f72015-06-15 09:41:06 +02006328 /* process rpc's specific children */
6329 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006330 if (strcmp(sub->ns->value, LY_NSYIN)) {
6331 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006332 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006333 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006334 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006335 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006336 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006337 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006338 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006339 goto error;
6340 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006341 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006342 lyxml_unlink_elem(ctx, sub, 2);
6343 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006344 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006345 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006346 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006347 goto error;
6348 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006349 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006350 lyxml_unlink_elem(ctx, sub, 2);
6351 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006353 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006354 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006355 lyxml_unlink_elem(ctx, sub, 2);
6356 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006358 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006359 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006360 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006361 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006362 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006363 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006364 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006365 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006366 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006367 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006368 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006369 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006370 }
6371 }
6372
6373 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6374 if (c_tpdf) {
6375 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006376 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006377 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006378 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006379 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006380 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006381 }
Radek Krejcie534c132016-11-23 13:32:31 +01006382 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006383 /* some extensions may be already present from the substatements */
6384 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006385 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006386 retval->ext = reallocated;
6387
6388 /* init memory */
6389 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006390 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006391
Radek Krejcie534c132016-11-23 13:32:31 +01006392 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6393 if (strcmp(sub->ns->value, LY_NSYIN)) {
6394 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006395 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 +01006396 retval->ext_size++;
6397 if (r) {
6398 goto error;
6399 }
6400 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006401 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6402 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006403 if (r) {
6404 goto error;
6405 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006406 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006407 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006408 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006409 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006410 goto error;
6411 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006412 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006413 }
6414
6415 /* last part - process data nodes */
6416 LY_TREE_FOR_SAFE(root.child, next, sub) {
6417 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006418 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006419 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006420 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006421 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006422 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006423 goto error;
6424 }
Radek Krejci73adb602015-07-02 18:07:40 +02006425
Michal Vasko53b7da02018-02-13 15:28:42 +01006426 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006427 }
6428
Michal Vasko38d01f72015-06-15 09:41:06 +02006429 return retval;
6430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006431error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006432 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006433 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006434 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006435 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006436 return NULL;
6437}
6438
Michal Vasko0d343d12015-08-24 14:57:36 +02006439/* logs directly
6440 *
Radek Krejci74705112015-06-05 10:25:44 +02006441 * resolve - referenced grouping should be bounded to the namespace (resolved)
6442 * only when uses does not appear in grouping. In a case of grouping's uses,
6443 * we just get information but we do not apply augment or refine to it.
6444 */
Radek Krejci76512572015-08-04 09:47:08 +02006445static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006446read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6447 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006448{
Michal Vasko53b7da02018-02-13 15:28:42 +01006449 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006450 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006451 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006452 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006453 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006454 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006455 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006456 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006458 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006459 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006460
Radek Krejci76512572015-08-04 09:47:08 +02006461 uses->nodetype = LYS_USES;
6462 uses->prev = (struct lys_node *)uses;
6463 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006464
Michal Vasko53b7da02018-02-13 15:28:42 +01006465 GETVAL(ctx, value, yin, "name");
6466 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006467
Radek Krejci07d0fb92017-01-13 14:11:05 +01006468 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006469 goto error;
6470 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006471
Michal Vasko3e3228d2017-02-24 14:55:32 +01006472 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006473
Radek Krejcic189a952016-07-11 15:27:07 +02006474 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006475 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006476 goto error;
6477 }
6478
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006479 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006480 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006481 if (strcmp(sub->ns->value, LY_NSYIN)) {
6482 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006483 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006484 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006485 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006486 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006487 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006488 c_ref++;
6489 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006490 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006491 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006492 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006493 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006494 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006495 } else if (!strcmp(sub->name, "when")) {
6496 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006497 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006498 goto error;
6499 }
6500
Radek Krejci5323b492017-01-16 15:40:11 +01006501 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006502 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006503 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006504 goto error;
6505 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006506 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006507 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006508 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006509 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006510 }
6511 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006513 /* process properties with cardinality 0..n */
6514 if (c_ref) {
6515 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006516 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006517 }
6518 if (c_aug) {
6519 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006520 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006521 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006522 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006523 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006524 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006525 }
Radek Krejcie534c132016-11-23 13:32:31 +01006526 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006527 /* some extensions may be already present from the substatements */
6528 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006529 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006530 retval->ext = reallocated;
6531
6532 /* init memory */
6533 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006534 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006535
Radek Krejcie534c132016-11-23 13:32:31 +01006536 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6537 if (strcmp(sub->ns->value, LY_NSYIN)) {
6538 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006539 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 +01006540 retval->ext_size++;
6541 if (r) {
6542 goto error;
6543 }
6544 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006545 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006546 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006547 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006548 goto error;
6549 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006550 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006551 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006552 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006553 if (r) {
6554 goto error;
6555 }
6556 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006557 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006558 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006559 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006560 goto error;
6561 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006562 }
6563 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006564
Radek Krejci48464ed2016-03-17 15:44:09 +01006565 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006566 goto error;
6567 }
Radek Krejci74705112015-06-05 10:25:44 +02006568
Michal Vasko508a50d2016-09-07 14:50:33 +02006569 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006570 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006571 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006572 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006573 goto error;
6574 }
6575 } else {
6576 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6577 goto error;
6578 }
6579 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006580 }
6581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006582 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006583
6584error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006585 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006586 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006587}
6588
Michal Vasko0d343d12015-08-24 14:57:36 +02006589/* logs directly
6590 *
6591 * common code for yin_read_module() and yin_read_submodule()
6592 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006593static int
Radek Krejcic071c542016-01-27 14:57:51 +01006594read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6595 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006596{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006597 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006598 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006599 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006600 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006601 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006602 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006603 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006604 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6605 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6606 int substmt_group;
6607 /* just remember last substatement for logging */
6608 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006609 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006610 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;
6611 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006612 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006613
Radek Krejcic071c542016-01-27 14:57:51 +01006614 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006615 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006617 /* init */
6618 memset(&root, 0, sizeof root);
6619 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006620 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006621 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006622 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006624 /*
6625 * in the first run, we process elements with cardinality of 1 or 0..1 and
6626 * count elements with cardinality 0..n. Data elements (choices, containers,
6627 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6628 * need have all top-level and groupings already prepared at that time. In
6629 * the middle loop, we process other elements with carinality of 0..n since
6630 * we need to allocate arrays to store them.
6631 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006632 substmt_group = 0;
6633 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006634 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006635 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006636 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006637 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006638 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006639 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006640 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006641 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006642 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006643 lyxml_unlink_elem(ctx, child, 2);
6644 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006645 c_extinst++;
6646 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006647 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006648 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6649 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006650 child->name, substmt_prev);
6651 goto error;
6652 }
6653
PavolVican9e81c6a2017-02-09 13:09:07 +01006654 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006655 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006656 goto error;
6657 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006658 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006659 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006660
Radek Krejci8d6b7422017-02-03 14:42:13 +01006661 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006662 goto error;
6663 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006664 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006665
6666 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006667 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006668 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006669 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6670 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006671 child->name, substmt_prev);
6672 goto error;
6673 }
6674
PavolVican9e81c6a2017-02-09 13:09:07 +01006675 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006676 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006677 goto error;
6678 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006679 GETVAL(ctx, value, child, "value");
6680 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006681 goto error;
6682 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006683 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006684
Radek Krejci8d6b7422017-02-03 14:42:13 +01006685 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006686 goto error;
6687 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006688 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006689
6690 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006691 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006692 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006693 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6694 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006695 child->name, substmt_prev);
6696 goto error;
6697 }
6698
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006699 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006700 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006701 goto error;
6702 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006703 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006704 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006705 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006706 goto error;
6707 }
Radek Krejcif3886932015-06-04 17:36:06 +02006708
Radek Krejci8d6b7422017-02-03 14:42:13 +01006709 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006710 goto error;
6711 }
6712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006713 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006714 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006715 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006716 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006717 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006718 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006719 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006720 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006721 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006722 goto error;
6723 }
6724 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006725 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006726 /* check here differs from a generic prefix check, since this prefix
6727 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006728 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006729 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006730 goto error;
6731 }
Radek Krejcic071c542016-01-27 14:57:51 +01006732 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006733
Radek Krejci8d6b7422017-02-03 14:42:13 +01006734 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 +01006735 goto error;
6736 }
6737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006738 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006739 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006740
Michal Vasko5de8a022017-02-08 10:57:26 +01006741 substmt_prev = "belongs-to";
6742
Radek Krejcieb00f512015-07-01 16:44:58 +02006743 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006744 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006745 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006746 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6747 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006748 child->name, substmt_prev);
6749 goto error;
6750 }
6751 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006752 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006753 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006754 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006755
6756 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006757 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006758 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006759 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6760 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006761 child->name, substmt_prev);
6762 goto error;
6763 }
6764 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006765 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006766 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006767 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006768
PavolVican9e81c6a2017-02-09 13:09:07 +01006769 lyxml_unlink_elem(ctx, child, 2);
6770 lyxml_add_child(ctx, &revs, child);
6771
Michal Vasko5de8a022017-02-08 10:57:26 +01006772 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006773 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006774 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006775 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006776 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006777 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006778
6779 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006780 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006781 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006782 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006783 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006784 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006785
6786 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006787 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006788 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006789 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6790 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006791 child->name, substmt_prev);
6792 goto error;
6793 }
6794 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006795 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006796 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006797 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006798
6799 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006800 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006801 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006802 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006803 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006804 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006805 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006806 lyxml_unlink_elem(ctx, child, 2);
6807 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006808
Michal Vasko5de8a022017-02-08 10:57:26 +01006809 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006810 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006811 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006812 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006813 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006814 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006815
Michal Vasko5de8a022017-02-08 10:57:26 +01006816 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006818 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006819 } else if (!strcmp(child->name, "container") ||
6820 !strcmp(child->name, "leaf-list") ||
6821 !strcmp(child->name, "leaf") ||
6822 !strcmp(child->name, "list") ||
6823 !strcmp(child->name, "choice") ||
6824 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006825 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006826 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006827 !strcmp(child->name, "rpc") ||
6828 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006829 substmt_group = 4;
6830
Radek Krejcic071c542016-01-27 14:57:51 +01006831 lyxml_unlink_elem(ctx, child, 2);
6832 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006833
Michal Vasko5de8a022017-02-08 10:57:26 +01006834 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006835 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006836 substmt_group = 4;
6837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006838 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006839 lyxml_unlink_elem(ctx, child, 2);
6840 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006841
Michal Vasko5de8a022017-02-08 10:57:26 +01006842 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006843 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006844 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006845 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006846 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6847 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006848 child->name, substmt_prev);
6849 goto error;
6850 }
6851 substmt_group = 2;
6852
Radek Krejcic071c542016-01-27 14:57:51 +01006853 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006854 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006855 goto error;
6856 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006857 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006858 goto error;
6859 }
Radek Krejcic071c542016-01-27 14:57:51 +01006860 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006861 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006862 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006863 goto error;
6864 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006865
6866 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006867 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006868 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006869 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6870 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006871 child->name, substmt_prev);
6872 goto error;
6873 }
6874 substmt_group = 2;
6875
Radek Krejcic071c542016-01-27 14:57:51 +01006876 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006877 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006878 goto error;
6879 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006880 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006881 goto error;
6882 }
Radek Krejcic071c542016-01-27 14:57:51 +01006883 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006884 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006885 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006886 goto error;
6887 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006888
6889 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006890 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006891 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006892 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6893 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006894 child->name, substmt_prev);
6895 goto error;
6896 }
6897 substmt_group = 2;
6898
Radek Krejcic071c542016-01-27 14:57:51 +01006899 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006900 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006901 goto error;
6902 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006903 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006904 goto error;
6905 }
Radek Krejcic071c542016-01-27 14:57:51 +01006906 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006907 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006908 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006909 goto error;
6910 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006911
6912 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006913 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006914 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006915 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6916 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006917 child->name, substmt_prev);
6918 goto error;
6919 }
6920 substmt_group = 2;
6921
Radek Krejcic071c542016-01-27 14:57:51 +01006922 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006923 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006924 goto error;
6925 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006926 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006927 goto error;
6928 }
Radek Krejcic071c542016-01-27 14:57:51 +01006929 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006930 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006931 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006932 goto error;
6933 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006934
6935 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006936 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006937 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006938 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6939 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006940 child->name, substmt_prev);
6941 goto error;
6942 }
6943
Radek Krejcic071c542016-01-27 14:57:51 +01006944 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006945 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006946 goto error;
6947 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006948 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006949 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006950 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006951 goto error;
6952 }
Radek Krejcic071c542016-01-27 14:57:51 +01006953 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006954 if (!strcmp(value, "1")) {
6955 if (submodule) {
6956 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006957 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006958 goto error;
6959 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006960 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006961 } else {
6962 module->version = 1;
6963 }
6964 } else {
6965 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006966 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006967 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006968 goto error;
6969 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006970 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006971 } else {
6972 module->version = 2;
6973 }
6974 }
6975
Radek Krejci8d6b7422017-02-03 14:42:13 +01006976 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006977 goto error;
6978 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006979 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006980
Michal Vasko5de8a022017-02-08 10:57:26 +01006981 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006982 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006983 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006984 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006985 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006986 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006987
Michal Vasko5de8a022017-02-08 10:57:26 +01006988 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006989 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006990 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006991 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006992 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006993 c_dev++;
6994
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006995 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006996 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006997 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006998 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006999 }
7000 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007001
Radek Krejcic071c542016-01-27 14:57:51 +01007002 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01007003 if (submodule) {
7004 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007005 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01007006 goto error;
7007 }
7008 if (!version_flag) {
7009 /* check version compatibility with the main module */
7010 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007011 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01007012 goto error;
7013 }
7014 }
7015 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01007016 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007017 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007018 goto error;
7019 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007020 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007021 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007022 goto error;
7023 }
7024 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02007025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007026 /* allocate arrays for elements with cardinality of 0..n */
7027 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007028 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01007029 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007030 }
7031 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007032 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01007033 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007034 }
7035 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01007036 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01007037 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007038 }
7039 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01007040 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01007041 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007042 }
7043 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007044 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01007045 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007046 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007047 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01007048 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01007049 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007050 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02007051 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01007052 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007053 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007054 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007055 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007056 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007057 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007058 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007059 if (c_ext) {
7060 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007061 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007062 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007063
PavolVican9e81c6a2017-02-09 13:09:07 +01007064 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7065 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007066 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7067 trg->rev_size++;
7068 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007069 goto error;
7070 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007071
Radek Krejci7417a082017-02-16 11:07:59 +01007072 /* check uniqueness of the revision date - not required by RFC */
7073 for (i = 0; i < (trg->rev_size - 1); i++) {
7074 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007075 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007076 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007077 }
7078 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007079
7080 lyxml_free(ctx, child);
7081 }
7082
7083 /* check the module with respect to the context now */
7084 if (!submodule) {
7085 switch (lyp_ctx_check_module(module)) {
7086 case -1:
7087 goto error;
7088 case 0:
7089 break;
7090 case 1:
7091 /* it's already there */
7092 ret = 1;
7093 goto error;
7094 }
7095 }
7096
PavolVican92f23622017-12-12 13:35:56 +01007097 /* check first definition of extensions */
7098 if (c_ext) {
7099 LY_TREE_FOR_SAFE(yin->child, next, child) {
7100 if (!strcmp(child->name, "extension")) {
7101 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7102 trg->extensions_size++;
7103 if (r) {
7104 goto error;
7105 }
7106
7107 }
7108 }
7109 }
7110
PavolVican9e81c6a2017-02-09 13:09:07 +01007111 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007112 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007113 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007114 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007115 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007116 if (r) {
7117 goto error;
7118 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007119
Radek Krejci1d82ef62015-08-07 14:44:40 +02007120 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007121 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7122 trg->inc_size++;
7123 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007124 goto error;
7125 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007126
Radek Krejci1d82ef62015-08-07 14:44:40 +02007127 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007128 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7129 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007130 if (r) {
7131 goto error;
7132 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007133
Radek Krejci1d82ef62015-08-07 14:44:40 +02007134 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007135 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7136 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007137 if (r) {
7138 goto error;
7139 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007140
Radek Krejci1d82ef62015-08-07 14:44:40 +02007141 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007142 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7143 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007144 if (r) {
7145 goto error;
7146 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007147
Radek Krejci1d82ef62015-08-07 14:44:40 +02007148 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko0f437062018-06-08 15:52:39 +02007149 /* must be implemented in this case */
7150 trg->implemented = 1;
7151
Radek Krejcic071c542016-01-27 14:57:51 +01007152 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7153 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007154 if (r) {
7155 goto error;
7156 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007157 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007158 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007159
Radek Krejcie534c132016-11-23 13:32:31 +01007160 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007161 if (c_extinst) {
7162 /* some extensions may be already present from the substatements */
7163 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007164 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007165 trg->ext = reallocated;
7166
7167 /* init memory */
7168 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7169
7170 LY_TREE_FOR_SAFE(exts.child, next, child) {
7171 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7172 trg->ext_size++;
7173 if (r) {
7174 goto error;
7175 }
7176 }
Radek Krejcie534c132016-11-23 13:32:31 +01007177 }
7178
Radek Krejcif5be10f2015-06-16 13:29:36 +02007179 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007180 * refer to them. Submodule's data nodes are stored in the
7181 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007182 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007183 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007184 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007185 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007186 goto error;
7187 }
Radek Krejci74705112015-06-05 10:25:44 +02007188
Michal Vasko345da0a2015-12-02 10:35:55 +01007189 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007190 }
Radek Krejci74705112015-06-05 10:25:44 +02007191
Radek Krejcif5be10f2015-06-16 13:29:36 +02007192 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007193 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007194
Radek Krejci1d82ef62015-08-07 14:44:40 +02007195 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007196 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007197 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007198 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007199 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007200 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007201 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007202 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007203 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007204 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007205 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007206 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007207 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007208 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007209 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007210 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007211 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007212 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007213 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007214 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007215 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007216 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007217 goto error;
7218 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007219
Michal Vasko345da0a2015-12-02 10:35:55 +01007220 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007221 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007222
Michal Vasko2f7925f2015-10-21 15:06:56 +02007223 /* ... and finally augments (last, so we can augment our data, for instance) */
7224 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007225 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007226 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007227
Michal Vasko2f7925f2015-10-21 15:06:56 +02007228 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007229 goto error;
7230 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007231 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007232 }
7233
PavolVican9e81c6a2017-02-09 13:09:07 +01007234 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007235
7236error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007237 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007238 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007239 }
7240 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007241 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007242 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007243 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007244 lyxml_free(ctx, augs.child);
7245 }
7246 while (revs.child) {
7247 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007248 }
Radek Krejcie534c132016-11-23 13:32:31 +01007249 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007250 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007251 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007252
PavolVican9e81c6a2017-02-09 13:09:07 +01007253 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007254}
7255
Michal Vasko0d343d12015-08-24 14:57:36 +02007256/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007257struct lys_submodule *
7258yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007259{
Michal Vasko53b7da02018-02-13 15:28:42 +01007260 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007261 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007262 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007263 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007264
Michal Vasko53b7da02018-02-13 15:28:42 +01007265 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007266 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007267 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007268 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007270 /* check root element */
7271 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007272 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007273 goto error;
7274 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007275
Michal Vasko53b7da02018-02-13 15:28:42 +01007276 GETVAL(ctx, value, yin, "name");
7277 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007278 goto error;
7279 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007280
Michal Vasko5a721fd2016-02-16 12:16:48 +01007281 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007282 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007283
Michal Vasko53b7da02018-02-13 15:28:42 +01007284 submodule->ctx = ctx;
7285 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007286 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007287 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007288 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007289
Radek Krejci9e757e02017-03-08 17:18:09 +01007290 /* add into the list of processed modules */
7291 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7292 goto error;
7293 }
7294
Michal Vasko5a721fd2016-02-16 12:16:48 +01007295 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007296 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007297 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007298 goto error;
7299 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007300
Radek Krejci33fc4772017-01-26 16:00:35 +01007301 lyp_sort_revisions((struct lys_module *)submodule);
7302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007303 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007304 lyxml_free(ctx, yin);
7305 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007306
Michal Vasko5a721fd2016-02-16 12:16:48 +01007307 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007308 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007309
7310error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007311 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007312 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007313 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007314 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007315 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007316 }
7317
Michal Vasko53b7da02018-02-13 15:28:42 +01007318 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007319
Michal Vaskoa9728122018-01-16 14:00:13 +01007320 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007321 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007322 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7323 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007324 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007325 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007326}
7327
Michal Vasko0d343d12015-08-24 14:57:36 +02007328/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007329struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007330yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007331{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007332 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007333 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007334 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007335 int ret;
Michal Vasko7d4c0172020-01-20 14:21:35 +01007336 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02007337
Radek Krejcic071c542016-01-27 14:57:51 +01007338 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007339 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007341 /* check root element */
7342 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007343 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007344 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007345 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007346 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007347 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007348 goto error;
7349 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007350
Michal Vasko53b7da02018-02-13 15:28:42 +01007351 GETVAL(ctx, value, yin, "name");
7352 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007353 goto error;
7354 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007355
Michal Vasko7d4c0172020-01-20 14:21:35 +01007356 /* in some really invalid situations there can be a circular import and
7357 * we can check it only after we have parsed the module name */
7358 for (i = 0; i < ctx->models.parsing_sub_modules_count; ++i) {
7359 if (!strcmp(ctx->models.parsing_sub_modules[i]->name, value)) {
7360 LOGVAL(ctx, LYE_CIRC_IMPORTS, LY_VLOG_NONE, NULL, value);
7361 goto error;
7362 }
7363 }
7364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007365 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007366 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007368 module->ctx = ctx;
7369 module->name = lydict_insert(ctx, value, strlen(value));
7370 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007371 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007372
Radek Krejci9e757e02017-03-08 17:18:09 +01007373 /* add into the list of processed modules */
7374 if (lyp_check_circmod_add(module)) {
7375 goto error;
7376 }
7377
Michal Vasko9f258e42016-02-11 11:36:27 +01007378 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007379 ret = read_sub_module(module, NULL, yin, unres);
7380 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007381 goto error;
7382 }
7383
PavolVican9e81c6a2017-02-09 13:09:07 +01007384 if (ret == 1) {
7385 assert(!unres->count);
7386 } else {
Michal Vasko0f437062018-06-08 15:52:39 +02007387 /* make this module implemented if was not from start */
7388 if (!implement && module->implemented && (unres_schema_add_node(module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1)) {
7389 goto error;
7390 }
7391
PavolVican9e81c6a2017-02-09 13:09:07 +01007392 /* resolve rest of unres items */
7393 if (unres->count && resolve_unres_schema(module, unres)) {
7394 goto error;
7395 }
7396
7397 /* check correctness of includes */
7398 if (lyp_check_include_missing(module)) {
7399 goto error;
7400 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007401 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007402
Radek Krejci95f22ae2017-01-20 14:25:53 +01007403 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007404
7405 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7406 goto error;
7407 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007408
Radek Krejciff4874d2016-03-07 12:30:50 +01007409 if (revision) {
7410 /* check revision of the parsed model */
7411 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007412 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7413 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007414 goto error;
7415 }
7416 }
7417
PavolVican9e81c6a2017-02-09 13:09:07 +01007418 /* add into context if not already there */
7419 if (!ret) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007420 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007421 goto error;
7422 }
Michal Vasko10681e82018-01-16 14:54:16 +01007423
7424 /* remove our submodules from the parsed submodules list */
7425 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007426 } else {
7427 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007428 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007429
7430 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007431 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007432 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007433 }
7434
Michal Vasko44ab1462017-05-18 13:18:36 +02007435 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007436 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007437 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7438 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007439 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007440
7441error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007442 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007443 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007444
7445 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007446 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7447 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007448 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007449 return NULL;
7450 }
7451
Michal Vasko53b7da02018-02-13 15:28:42 +01007452 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007453
Radek Krejci9e757e02017-03-08 17:18:09 +01007454 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007455 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007456 lyp_del_includedup(module, 1);
7457 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007458 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007459}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007460
Radek Krejci37f9ba32017-02-10 16:50:35 +01007461/* logs directly */
7462struct lys_module *
7463yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7464{
7465 struct lyxml_elem *yin;
7466 struct lys_module *result;
7467
Radek Krejcie1bacd72017-03-01 13:18:46 +01007468 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007469 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007470 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007471 return NULL;
7472 }
7473
7474 result = yin_read_module_(ctx, yin, revision, implement);
7475
7476 lyxml_free(ctx, yin);
7477
7478 return result;
7479}
7480
Radek Krejcic1885952017-02-07 09:37:51 +01007481static int
7482yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007483 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007484 const char *true_val, const char *false_val, struct unres_schema *unres)
7485{
7486 uint8_t *val;
7487 const char *str;
7488 struct lyext_substmt *info;
7489
7490 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7491 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007492 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007493 return EXIT_FAILURE;
7494 }
7495 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007496 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007497 return EXIT_FAILURE;
7498 }
7499
Radek Krejcidb35f172017-02-27 11:03:01 +01007500 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007501 return EXIT_FAILURE;
7502 }
7503
7504 str = lyxml_get_attr(node, "value", NULL);
7505 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007506 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007507 } else if (true_val && !strcmp(true_val, str)) {
7508 /* true value */
7509 *val = 1;
7510 } else if (false_val && !strcmp(false_val, str)) {
7511 /* false value */
7512 *val = 2;
7513 } else {
7514 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007515 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007516 return EXIT_FAILURE;
7517 }
7518
7519 return EXIT_SUCCESS;
7520}
7521
Radek Krejci8d6b7422017-02-03 14:42:13 +01007522/*
7523 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7524 * argname - name of the element/attribute where the value is stored
7525 */
7526static int
7527yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007528 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007529 int argelem, const char *argname, struct unres_schema *unres)
7530{
7531 int c;
PavolVican99c70722017-02-18 17:25:52 +01007532 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007533 void *reallocated;
7534 struct lyext_substmt *info;
7535
7536 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7537 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007538 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007539 return EXIT_FAILURE;
7540 }
7541 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007542 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007543 return EXIT_FAILURE;
7544 }
7545
7546 c = 0;
7547 if (info->cardinality >= LY_STMT_CARD_SOME) {
7548 /* there can be multiple instances, str is actually const char *** */
7549 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007550 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007551 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007552 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007553 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007554 if (stmt == LY_STMT_BELONGSTO) {
7555 /* allocate another array for the belongs-to's prefixes */
7556 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007557 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007558 } else if (stmt == LY_STMT_ARGUMENT) {
7559 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007560 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007561 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007562 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007563 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007564 /* get the index in the array to add new item */
7565 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007566 }
Radek Krejci56c80412017-02-09 10:44:16 +01007567 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007568 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007569 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007570 return EXIT_FAILURE;
7571 }
7572
7573 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007574 str[c] = read_yin_subnode(mod->ctx, node, argname);
7575 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007576 return EXIT_FAILURE;
7577 }
Radek Krejci56c80412017-02-09 10:44:16 +01007578 } else {
7579 str[c] = lyxml_get_attr(node, argname, NULL);
7580 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007581 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007582 return EXIT_FAILURE;
7583 } else {
7584 str[c] = lydict_insert(mod->ctx, str[c], 0);
7585 }
7586
7587 if (stmt == LY_STMT_BELONGSTO) {
7588 /* get the belongs-to's mandatory prefix substatement */
7589 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007590 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007591 return EXIT_FAILURE;
7592 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007593 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007594 return EXIT_FAILURE;
7595 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007596 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007597 return EXIT_FAILURE;
7598 }
7599 /* and now finally get the value */
7600 if (p) {
7601 str = p[1];
7602 } else {
7603 str++;
7604 }
7605 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7606 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007607 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007608 return EXIT_FAILURE;
7609 }
7610 str[c] = lydict_insert(mod->ctx, str[c], 0);
7611
PavolVican6d400872017-03-01 15:19:18 +01007612 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 +01007613 return EXIT_FAILURE;
7614 }
PavolVican99c70722017-02-18 17:25:52 +01007615 } else if (stmt == LY_STMT_ARGUMENT) {
7616 str = (p) ? p[1] : str + 1;
7617 if (!node->child) {
7618 /* default value of yin element */
7619 ((uint8_t *)str)[c] = 2;
7620 } else {
7621 /* get optional yin-element substatement */
7622 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007623 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007624 return EXIT_FAILURE;
7625 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007626 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007627 return EXIT_FAILURE;
7628 } else {
7629 /* and now finally get the value */
7630 value = lyxml_get_attr(node->child, "value", NULL);
7631 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007632 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007633 return EXIT_FAILURE;
7634 }
7635 if (ly_strequal(value, "true", 0)) {
7636 ((uint8_t *)str)[c] = 1;
7637 } else if (ly_strequal(value, "false", 0)) {
7638 ((uint8_t *)str)[c] = 2;
7639 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007640 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007641 return EXIT_FAILURE;
7642 }
7643
7644 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7645 return EXIT_FAILURE;
7646 }
7647 }
7648 }
Radek Krejci56c80412017-02-09 10:44:16 +01007649 }
7650 }
7651 if (p) {
7652 /* enlarge the array(s) */
7653 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7654 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007655 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007656 lydict_remove(mod->ctx, p[0][c]);
7657 p[0][c] = NULL;
7658 return EXIT_FAILURE;
7659 }
7660 p[0] = reallocated;
7661 p[0][c + 1] = NULL;
7662
7663 if (stmt == LY_STMT_BELONGSTO) {
7664 /* enlarge the second belongs-to's array with prefixes */
7665 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7666 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007667 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007668 lydict_remove(mod->ctx, p[1][c]);
7669 p[1][c] = NULL;
7670 return EXIT_FAILURE;
7671 }
7672 p[1] = reallocated;
7673 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007674 } else if (stmt == LY_STMT_ARGUMENT){
7675 /* enlarge the second argument's array with yin element */
7676 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7677 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007678 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007679 ((uint8_t *)p[1])[c] = 0;
7680 return EXIT_FAILURE;
7681 }
7682 p[1] = reallocated;
7683 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007684 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007685 }
7686
7687 return EXIT_SUCCESS;
7688}
7689
7690static void *
7691yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7692 uint16_t mask)
7693{
7694 void *data;
7695 struct lyext_substmt *info;
7696
7697 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7698 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007699 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007700 return NULL;
7701 }
7702 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007703 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007704 return NULL;
7705 }
7706
7707 return data;
7708}
7709
Radek Krejcic1885952017-02-07 09:37:51 +01007710static int
7711yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007712 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007713 const char *val1_str, const char *val2_str, uint16_t mask,
7714 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7715{
7716 uint16_t *val;
7717 const char *str;
7718
7719 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7720 if (!val) {
7721 return EXIT_FAILURE;
7722 }
7723
7724 str = lyxml_get_attr(node, "value", NULL);
7725 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007726 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007727 } else if (!strcmp(val1_str, str)) {
7728 *val = *val | val1;
7729 } else if (!strcmp(val2_str, str)) {
7730 *val = *val | val2;
7731 } else {
7732 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007733 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007734 return EXIT_FAILURE;
7735 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007736 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007737 return EXIT_FAILURE;
7738 }
7739 return EXIT_SUCCESS;
7740}
7741
Radek Krejcif95b6292017-02-13 15:57:37 +01007742static struct lys_node **
7743yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7744{
7745 struct lyext_substmt *info;
7746 struct lys_node **snode, *siter;
7747
7748 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7749 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007750 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007751 return NULL;
7752 }
7753 if (info->cardinality < LY_STMT_CARD_SOME) {
7754 LY_TREE_FOR(*snode, siter) {
7755 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007756 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007757 return NULL;
7758 }
7759 }
7760 }
7761
7762 return snode;
7763}
7764
Radek Krejci8d6b7422017-02-03 14:42:13 +01007765static void **
7766yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7767{
7768 int c;
7769 void **data, ***p = NULL;
7770 void *reallocated;
7771 struct lyext_substmt *info;
7772
7773 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7774 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007775 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007776 return NULL;
7777 }
7778 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007779 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007780 return NULL;
7781 }
7782
7783 c = 0;
7784 if (info->cardinality >= LY_STMT_CARD_SOME) {
7785 /* there can be multiple instances, so instead of pointer to array,
7786 * we have in data pointer to pointer to array */
7787 p = (void ***)data;
7788 data = *p;
7789 if (!data) {
7790 /* allocate initial array */
7791 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007792 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007793 } else {
7794 for (c = 0; *data; data++, c++);
7795 }
7796 }
7797
7798 if (p) {
7799 /* enlarge the array */
7800 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007801 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007802 *p = reallocated;
7803 data = *p;
7804 data[c + 1] = NULL;
7805 }
7806
7807 return &data[c];
7808}
7809
7810int
7811lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7812 struct unres_schema *unres)
7813{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007814 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007815 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007816 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007817 const char *value, *name;
7818 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007819 struct lyext_substmt *info;
7820 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007821 long long int ll;
7822 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007823 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007824
Radek Krejcia8d111f2017-05-31 13:57:37 +02007825#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7826 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007827 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007828 (**(TYPE **)TO) = (TYPE)FROM;
7829
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007830#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007831 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7832 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007833 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007834 goto error; \
7835 } \
7836 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007837 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007838 goto error; \
7839 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007840 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007841 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7842 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007843 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007844 if (!(*pp)) { \
7845 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007846 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007847 } else { \
7848 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7849 } \
7850 p = &(*(TYPE**)pp)[i]; \
7851 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007852#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007853 if (pp) { \
7854 /* enlarge the array */ \
7855 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007856 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007857 *pp = reallocated; \
7858 (*(TYPE**)pp)[i + 1] = 0; \
7859 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007860#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7861 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7862 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007863 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007864#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7865 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007866 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007867 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007868 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007869 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7870 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7871 goto error; \
7872 } \
7873 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007874
Radek Krejci8d6b7422017-02-03 14:42:13 +01007875 LY_TREE_FOR_SAFE(yin->child, next, node) {
7876 if (!node->ns) {
7877 /* garbage */
7878 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7879 /* we have the extension's argument */
7880 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007881 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007882 goto error;
7883 }
7884 ext->arg_value = node->content;
7885 node->content = NULL;
7886 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7887 /* extension */
7888 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7889 goto error;
7890 }
7891 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007892 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007893 goto error;
7894 }
7895 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007896 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007897 goto error;
7898 }
7899 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007900 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007901 goto error;
7902 }
7903 } else if (!strcmp(node->name, "type")) {
7904 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7905 if (!type) {
7906 goto error;
7907 }
7908 /* allocate type structure */
7909 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007910 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007911
7912 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007913 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007914 (*type)->der = (struct lys_tpdf *)node;
7915 (*type)->parent = (struct lys_tpdf *)ext;
7916
7917 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7918 (*type)->der = NULL;
7919 goto error;
7920 }
7921 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007922 } else if (!strcmp(node->name, "typedef")) {
7923 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7924 if (!pp) {
7925 goto error;
7926 }
7927 /* allocate typedef structure */
7928 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007929 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007930
7931 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7932 goto error;
7933 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007934 } else if (!strcmp(node->name, "if-feature")) {
7935 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7936 if (!pp) {
7937 goto error;
7938 }
7939 /* allocate iffeature structure */
7940 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007941 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007942
7943 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7944 goto error;
7945 }
7946 } else if (!strcmp(node->name, "status")) {
7947 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7948 if (!p) {
7949 goto error;
7950 }
7951
Michal Vasko53b7da02018-02-13 15:28:42 +01007952 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007953 if (!strcmp(value, "current")) {
7954 *(uint16_t*)p |= LYS_STATUS_CURR;
7955 } else if (!strcmp(value, "deprecated")) {
7956 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7957 } else if (!strcmp(value, "obsolete")) {
7958 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7959 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007960 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007961 goto error;
7962 }
7963
7964 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7965 goto error;
7966 }
Radek Krejcic1885952017-02-07 09:37:51 +01007967 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007968 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007969 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007970 goto error;
7971 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007972 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007973 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007974 goto error;
7975 }
7976 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007977 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007978 goto error;
7979 }
Radek Krejcic1885952017-02-07 09:37:51 +01007980 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007981 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007982 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7983 goto error;
7984 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007985 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007986 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007987 goto error;
7988 }
7989 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007990 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007991 goto error;
7992 }
7993 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007994 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007995 goto error;
7996 }
7997 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007998 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007999 goto error;
8000 }
8001 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008002 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008003 goto error;
8004 }
8005 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008006 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008007 goto error;
8008 }
8009 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008010 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008011 goto error;
8012 }
8013 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008014 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008015 goto error;
8016 }
Radek Krejcic1885952017-02-07 09:37:51 +01008017 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008018 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
8019 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008020 goto error;
8021 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008022 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008023 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008024 goto error;
8025 }
8026 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008027 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008028 goto error;
8029 }
8030 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008031 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008032 goto error;
8033 }
8034 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008035 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01008036 goto error;
8037 }
Radek Krejcic1885952017-02-07 09:37:51 +01008038 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008039 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008040 goto error;
8041 }
8042 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008043 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008044 goto error;
8045 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008046 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008047 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008048
Michal Vasko53b7da02018-02-13 15:28:42 +01008049 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008050 v = strtol(value, NULL, 10);
8051
8052 /* range check */
8053 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008054 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008055 goto error;
8056 }
8057
8058 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
8059 goto error;
8060 }
8061
8062 /* store the value */
8063 (*(uint8_t *)p) = (uint8_t)v;
8064
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008065 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008066 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008067 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008068
Michal Vasko53b7da02018-02-13 15:28:42 +01008069 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008070 while (isspace(value[0])) {
8071 value++;
8072 }
8073
8074 if (!strcmp(value, "unbounded")) {
8075 u = 0;
8076 } else {
8077 /* convert it to uint32_t */
8078 errno = 0; endptr = NULL;
8079 u = strtoul(value, &endptr, 10);
8080 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008081 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008082 goto error;
8083 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008084 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008085
8086 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8087 goto error;
8088 }
8089
8090 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008091 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008092
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008093 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008094 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008095 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008096
Michal Vasko53b7da02018-02-13 15:28:42 +01008097 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008098 while (isspace(value[0])) {
8099 value++;
8100 }
8101
8102 /* convert it to uint32_t */
8103 errno = 0;
8104 endptr = NULL;
8105 u = strtoul(value, &endptr, 10);
8106 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008107 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008108 goto error;
8109 }
8110
8111 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8112 goto error;
8113 }
8114
8115 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008116 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008117
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008118 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008119 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008120 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8121
Michal Vasko53b7da02018-02-13 15:28:42 +01008122 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008123 while (isspace(value[0])) {
8124 value++;
8125 }
8126
8127 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008128 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008129
8130 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008131 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008132 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008133 goto error;
8134 }
8135
8136 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8137 goto error;
8138 }
8139
8140 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008141 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008142
8143 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008144 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008145 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008146
Michal Vasko53b7da02018-02-13 15:28:42 +01008147 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008148 ll = strtoll(value, NULL, 10);
8149
8150 /* range check */
8151 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008152 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008153 goto error;
8154 }
8155
8156 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8157 goto error;
8158 }
8159
8160 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008161 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008162
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008163 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008164 } else if (!strcmp(node->name, "module")) {
8165 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8166 if (!pp) {
8167 goto error;
8168 }
8169
8170 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8171 if (!(*pp)) {
8172 goto error;
8173 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008174 } else if (!strcmp(node->name, "when")) {
8175 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8176
8177 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8178 if (!*(struct lys_when**)p) {
8179 goto error;
8180 }
8181
8182 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008183 } else if (!strcmp(node->name, "revision")) {
8184 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8185
8186 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008187 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008188 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8189 goto error;
8190 }
8191
8192 /* check uniqueness of the revision dates - not required by RFC */
8193 if (pp) {
8194 for (j = 0; j < i; j++) {
8195 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008196 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008197 }
8198 }
8199 }
8200
8201 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008202 } else if (!strcmp(node->name, "unique")) {
8203 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8204
8205 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008206 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008207 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8208 goto error;
8209 }
8210
8211 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8212 goto error;
8213 }
8214 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008215 } else if (!strcmp(node->name, "action")) {
8216 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8217 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008218 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008219 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008220 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008221 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008222 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008223 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008224 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008225 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008226 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008227 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008228 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008229 } else if (!strcmp(node->name, "output")) {
8230 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8231 } else if (!strcmp(node->name, "input")) {
8232 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8233 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008234 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008235 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008236 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008237 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008238 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008239 } else if (!strcmp(node->name, "notification")) {
8240 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8241 } else if (!strcmp(node->name, "uses")) {
8242 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008243 } else if (!strcmp(node->name, "length")) {
8244 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8245 } else if (!strcmp(node->name, "must")) {
8246 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8247 if (!pp) {
8248 goto error;
8249 }
8250 /* allocate structure for must */
8251 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008252 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008253
8254 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8255 goto error;
8256 }
8257 } else if (!strcmp(node->name, "pattern")) {
8258 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008259 GETVAL(mod->ctx, value, node, "value");
8260 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008261 goto error;
8262 }
8263
8264 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008265 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008266
8267 modifier = 0x06; /* ACK */
8268 if (mod->version >= 2) {
8269 name = NULL;
8270 LY_TREE_FOR(node->child, child) {
8271 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8272 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008273 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008274 goto error;
8275 }
8276
Michal Vasko53b7da02018-02-13 15:28:42 +01008277 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008278 if (!strcmp(name, "invert-match")) {
8279 modifier = 0x15; /* NACK */
8280 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008281 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008282 goto error;
8283 }
8284 /* get extensions of the modifier */
8285 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8286 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8287 goto error;
8288 }
8289 }
8290 }
8291 }
8292
8293 /* store the value: modifier byte + value + terminating NULL byte */
8294 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008295 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008296 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8297 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8298 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8299
8300 /* get possible sub-statements */
8301 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8302 goto error;
8303 }
8304
8305 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8306 } else if (!strcmp(node->name, "range")) {
8307 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008308 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008309 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008310 }
8311 lyxml_free(mod->ctx, node);
8312 }
8313
PavolVicanc4b798e2017-02-20 23:15:27 +01008314 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8315 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008316 }
8317
Radek Krejci8d6b7422017-02-03 14:42:13 +01008318 return EXIT_SUCCESS;
8319
8320error:
8321 return EXIT_FAILURE;
8322}