blob: 23b2e86d7e4d5f17ef115cb6f0e64cfb28d84b57 [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) {
251 if (!strcmp(child->ns->value, LY_NSYIN)) {
252 /* skip the regular YIN nodes */
253 continue;
254 }
255
256 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100257parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100258
Michal Vasko53b7da02018-02-13 15:28:42 +0100259 YIN_CHECK_ARRAY_OVERFLOW_RETURN(mod->ctx, *ext_size, *ext_size, "extension", statement, EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100260 /* first, allocate a space for the extension instance in the parent elem */
261 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100262 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100263 (*ext) = reallocated;
264
265 /* init memory */
266 (*ext)[(*ext_size)] = NULL;
267
268 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100269 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100270 (*ext_size)++;
271 if (r) {
272 return EXIT_FAILURE;
273 }
274
Radek Krejcifccd1442017-01-16 10:26:57 +0100275 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100276 }
277
Radek Krejcie534c132016-11-23 13:32:31 +0100278 return EXIT_SUCCESS;
279}
280
Michal Vasko0d343d12015-08-24 14:57:36 +0200281/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200282static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200283fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
284 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100285{
Radek Krejci5323b492017-01-16 15:40:11 +0100286 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100287 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100288 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100289 struct ly_ctx *ctx = parent->module->ctx;
Michal Vasko1d337e12016-02-15 12:32:04 +0100290
Michal Vasko53b7da02018-02-13 15:28:42 +0100291 GETVAL(ctx, value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200292
293 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100294 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200295error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100296 return EXIT_FAILURE;
297 }
298
Michal Vasko56d082c2016-10-25 14:00:42 +0200299 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100300 return EXIT_FAILURE;
301 }
302
Radek Krejci9de2c042016-10-19 16:53:06 +0200303 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko53b7da02018-02-13 15:28:42 +0100304 lydict_remove(ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200305 if (r) {
306 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100307 }
308
Radek Krejci5323b492017-01-16 15:40:11 +0100309 LY_TREE_FOR_SAFE(yin->child, next, node) {
310 if (!node->ns) {
311 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100312 lyxml_free(ctx, node);
Radek Krejci5323b492017-01-16 15:40:11 +0100313 } else if (strcmp(node->ns->value, LY_NSYIN)) {
314 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100315 YIN_CHECK_ARRAY_OVERFLOW_RETURN(ctx, c_ext, iffeat->ext_size, "extensions", "if-feature", EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100316 c_ext++;
317 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100318 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
Radek Krejci5323b492017-01-16 15:40:11 +0100319 return EXIT_FAILURE;
320 }
321 }
322 if (c_ext) {
323 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100324 LY_CHECK_ERR_RETURN(!iffeat->ext, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100325 LY_TREE_FOR_SAFE(yin->child, next, node) {
326 /* extensions */
327 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100328 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100329 iffeat->ext_size++;
330 if (r) {
331 return EXIT_FAILURE;
332 }
333 }
334 }
335
Radek Krejci9ff0a922016-07-14 13:08:05 +0200336 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100337}
338
339/* logs directly */
340static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200341fill_yin_identity(struct lys_module *module, struct lyxml_elem *yin, struct lys_ident *ident, struct unres_schema *unres)
Radek Krejci04581c62015-05-22 21:24:00 +0200342{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200343 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100344 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200345 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200346 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100347 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100348 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200349
Michal Vasko53b7da02018-02-13 15:28:42 +0100350 GETVAL(ctx, value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100351 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200352
Radek Krejci07d0fb92017-01-13 14:11:05 +0100353 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100354 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 }
Radek Krejci04581c62015-05-22 21:24:00 +0200356
Pavol Vicand6cda452016-07-13 15:08:29 +0200357 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100358 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200359 }
360
Radek Krejcie534c132016-11-23 13:32:31 +0100361 LY_TREE_FOR(yin->child, node) {
362 if (strcmp(node->ns->value, LY_NSYIN)) {
363 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100364 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ident->ext_size, "extensions", "identity", error);
Radek Krejcie534c132016-11-23 13:32:31 +0100365 c_ext++;
366 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200367 if (c_base && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100368 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100369 goto error;
370 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100371 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_base, ident->base_size, "bases", "identity", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +0100372 if (lyp_yin_parse_subnode_ext(module, ident, LYEXT_PAR_IDENT, node, LYEXT_SUBSTMT_BASE, c_base, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100373 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200374 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200375 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100376
Radek Krejci018f1f52016-08-03 16:01:20 +0200377 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100378 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, ident->iffeature_size, "if-features", "identity", error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200379 c_ftrs++;
380
381 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100382 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100383 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200384 }
385 }
386
387 if (c_base) {
388 ident->base_size = 0;
389 ident->base = calloc(c_base, sizeof *ident->base);
Michal Vasko53b7da02018-02-13 15:28:42 +0100390 LY_CHECK_ERR_GOTO(!ident->base, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200391 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200392 if (c_ftrs) {
393 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +0100394 LY_CHECK_ERR_GOTO(!ident->iffeature, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200395 }
Radek Krejcie534c132016-11-23 13:32:31 +0100396 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100397 /* some extensions may be already present from the substatements */
398 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100399 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci18a44882017-01-23 13:47:29 +0100400 ident->ext = reallocated;
401
402 /* init memory */
403 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100404 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200405
Radek Krejcie534c132016-11-23 13:32:31 +0100406 LY_TREE_FOR_SAFE(yin->child, next, node) {
407 if (strcmp(node->ns->value, LY_NSYIN)) {
408 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100409 rc = lyp_yin_fill_ext(ident, LYEXT_PAR_IDENT, 0, 0, module, node, &ident->ext, ident->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +0100410 ident->ext_size++;
411 if (rc) {
412 goto error;
413 }
414 } else if (!strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100415 GETVAL(ctx, value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100416 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100417 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100418 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200419 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100420
Radek Krejci48464ed2016-03-17 15:44:09 +0100421 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100422 lydict_remove(ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100423 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100424 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100425 lydict_remove(ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200426 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200427 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200428 ident->iffeature_size++;
429 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100430 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200431 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200432 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200433 }
Radek Krejci04581c62015-05-22 21:24:00 +0200434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200435 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200436
437error:
438 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200439}
440
Michal Vasko0d343d12015-08-24 14:57:36 +0200441/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200442static int
Radek Krejciaa9c5202017-02-15 16:10:14 +0100443read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
Radek Krejcifccd1442017-01-16 10:26:57 +0100444 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200445{
Radek Krejcifccd1442017-01-16 10:26:57 +0100446 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200447 const char *value;
Michal Vasko53b7da02018-02-13 15:28:42 +0100448 struct ly_ctx *ctx = module->ctx;
Radek Krejci41726f92015-06-19 13:11:05 +0200449
Radek Krejcifccd1442017-01-16 10:26:57 +0100450 LY_TREE_FOR_SAFE(yin->child, next, child) {
451 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200452 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200453 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100454 } else if (strcmp(child->ns->value, LY_NSYIN)) {
455 /* extension */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100456 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100457 return EXIT_FAILURE;
458 }
459 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200460 if (restr->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100461 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200462 return EXIT_FAILURE;
463 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100464 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100465 return EXIT_FAILURE;
466 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100467 restr->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200468 if (!restr->dsc) {
469 return EXIT_FAILURE;
470 }
471 } else if (!strcmp(child->name, "reference")) {
472 if (restr->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100473 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200474 return EXIT_FAILURE;
475 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100476 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100477 return EXIT_FAILURE;
478 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100479 restr->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200480 if (!restr->ref) {
481 return EXIT_FAILURE;
482 }
483 } else if (!strcmp(child->name, "error-app-tag")) {
484 if (restr->eapptag) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100485 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200486 return EXIT_FAILURE;
487 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100488 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100489 return EXIT_FAILURE;
490 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100491 GETVAL(ctx, value, child, "value");
492 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200493 } else if (!strcmp(child->name, "error-message")) {
494 if (restr->emsg) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100495 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200496 return EXIT_FAILURE;
497 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100498 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100499 return EXIT_FAILURE;
500 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100501 restr->emsg = read_yin_subnode(ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200502 if (!restr->emsg) {
503 return EXIT_FAILURE;
504 }
505 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100506 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200507 return EXIT_FAILURE;
508 }
Radek Krejci41726f92015-06-19 13:11:05 +0200509 }
510
511 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200512
513error:
514 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200515}
516
Michal Vasko88c29542015-11-27 14:57:53 +0100517/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
518int
Radek Krejcib8048692015-08-05 13:36:34 +0200519fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci8d6b7422017-02-03 14:42:13 +0100520 int parenttype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200521{
Michal Vasko568b1952018-01-30 15:53:30 +0100522 const char *value, *name, *module_name = NULL;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200523 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100524 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100525 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200526 struct lys_type_bit bit, *bits_sc = NULL;
527 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200528 struct lys_type *dertype;
Michal Vasko53b7da02018-02-13 15:28:42 +0100529 struct ly_ctx *ctx = module->ctx;
Radek Krejcidce5f972017-09-12 15:47:49 +0200530 int rc, val_set, c_ftrs, c_ext = 0;
531 unsigned int i, j;
Radek Krejcidc008d72016-02-17 13:12:14 +0100532 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200533 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200534 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200535 size_t len;
Radek Krejcib53154b2017-07-19 09:14:13 +0200536 int in_grp = 0;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200537 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200538
Radek Krejcie534c132016-11-23 13:32:31 +0100539 /* init */
540 memset(&exts, 0, sizeof exts);
541
Michal Vasko53b7da02018-02-13 15:28:42 +0100542 GETVAL(ctx, value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100543 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200544 if (!value) {
545 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200546 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200547
548 i = parse_identifier(value);
549 if (i < 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100550 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
551 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200552 goto error;
553 }
554 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100555 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200556 if (value[i]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100557 module_name = lydict_insert(ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100558 name += i;
559 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100560 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
561 lydict_remove(ctx, module_name);
562 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200563 goto error;
564 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200565 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100566 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200567 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200568
Michal Vasko568b1952018-01-30 15:53:30 +0100569 rc = resolve_superior_type(name, module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200570 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100571 LOGVAL(ctx, LYE_INMOD, LY_VLOG_NONE, NULL, module_name);
572 lydict_remove(ctx, module_name);
573 lydict_remove(ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200574 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100575
576 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200577 } else if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100578 LOGVAL(ctx, LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
579 lydict_remove(ctx, module_name);
580 lydict_remove(ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100581 ret = EXIT_FAILURE;
582 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100584 lydict_remove(ctx, module_name);
585 lydict_remove(ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200586
Michal Vasko101658e2018-06-05 15:05:54 +0200587 if (type->value_flags & LY_VALUE_UNRESGRP) {
Radek Krejcic13db382016-08-16 10:52:42 +0200588 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Michal Vasko70bf8e52018-03-26 11:32:33 +0200589 * unresolved item left inside the grouping, LYTYPE_GRP used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200590 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
591 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200592 assert(((struct lys_node_grp *)siter)->unres_count);
593 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200594 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100595 LOGINT(ctx);
Radek Krejcic13db382016-08-16 10:52:42 +0200596 goto error;
597 }
Michal Vasko101658e2018-06-05 15:05:54 +0200598 type->value_flags &= ~LY_VALUE_UNRESGRP;
Radek Krejcic13db382016-08-16 10:52:42 +0200599 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200600 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200601
Radek Krejcicf509982015-12-15 09:22:44 +0100602 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100603 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Michal Vasko53b7da02018-02-13 15:28:42 +0100604 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100605 return -1;
606 }
607
Radek Krejcie534c132016-11-23 13:32:31 +0100608 /* parse extension instances */
609 LY_TREE_FOR_SAFE(yin->child, next, node) {
610 if (!node->ns) {
611 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100612 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100613 continue;
614 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
615 /* YANG (YIN) statements - process later */
616 continue;
617 }
618
Michal Vasko53b7da02018-02-13 15:28:42 +0100619 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, type->ext_size, "extensions", "type", error);
Radek Krejcidce5f972017-09-12 15:47:49 +0200620
Michal Vasko53b7da02018-02-13 15:28:42 +0100621 lyxml_unlink_elem(ctx, node, 2);
622 lyxml_add_child(ctx, &exts, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100623 c_ext++;
624 }
625 if (c_ext) {
626 type->ext = calloc(c_ext, sizeof *type->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100627 LY_CHECK_ERR_GOTO(!type->ext, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200628
Radek Krejcie534c132016-11-23 13:32:31 +0100629 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100630 rc = lyp_yin_fill_ext(type, LYEXT_PAR_TYPE, 0, 0, module, node, &type->ext, type->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +0100631 type->ext_size++;
632 if (rc) {
633 goto error;
634 }
635 }
636 }
637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200640 /* RFC 6020 9.7.4 - bit */
641
642 /* get bit specifications, at least one must be present */
643 LY_TREE_FOR_SAFE(yin->child, next, node) {
644 if (!strcmp(node->name, "bit")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100645 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.bits.count, type->info.bits.count, "bits", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200646 type->info.bits.count = 0; goto error);
Radek Krejci994b6f62015-06-18 16:47:27 +0200647 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200648 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100649 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200650 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200651 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200652 }
653 }
Radek Krejcie663e012016-08-01 17:12:34 +0200654 dertype = &type->der->type;
655 if (!dertype->der) {
656 if (!type->info.bits.count) {
657 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100658 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200659 goto error;
660 }
661 } else {
662 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
663 if (module->version < 2 && type->info.bits.count) {
664 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
665 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100666 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200667 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200668 goto error;
669 }
Radek Krejciac781922015-07-09 15:35:14 +0200670 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200671
672 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +0100673 LY_CHECK_ERR_GOTO(!type->info.bits.bit, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200674
Radek Krejci73adb602015-07-02 18:07:40 +0200675 p = 0;
Michal Vaskoc643f712018-09-14 08:26:13 +0200676 i = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200677 LY_TREE_FOR(yin->child, next) {
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200678 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200679
Michal Vasko53b7da02018-02-13 15:28:42 +0100680 GETVAL(ctx, value, next, "name");
681 if (lyp_check_identifier(ctx, value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100682 goto error;
683 }
684
Michal Vasko53b7da02018-02-13 15:28:42 +0100685 type->info.bits.bit[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100686 if (read_yin_common(module, NULL, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, next, 0, unres)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200687 type->info.bits.count = i + 1;
688 goto error;
689 }
690
Radek Krejcie663e012016-08-01 17:12:34 +0200691 if (!dertype->der) { /* directly derived type from bits built-in type */
692 /* check the name uniqueness */
693 for (j = 0; j < i; j++) {
694 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100695 LOGVAL(ctx, LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejcie663e012016-08-01 17:12:34 +0200696 type->info.bits.count = i + 1;
697 goto error;
698 }
699 }
700 } else {
701 /* restricted bits type - the name MUST be used in the base type */
702 bits_sc = dertype->info.bits.bit;
703 for (j = 0; j < dertype->info.bits.count; j++) {
704 if (ly_strequal(bits_sc[j].name, value, 1)) {
705 break;
706 }
707 }
708 if (j == dertype->info.bits.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100709 LOGVAL(ctx, LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200710 type->info.bits.count = i + 1;
711 goto error;
712 }
713 }
714
Radek Krejcie663e012016-08-01 17:12:34 +0200715
Radek Krejci0d70c372015-07-02 16:23:10 +0200716 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100717 LY_TREE_FOR_SAFE(next->child, next2, node) {
718 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200719 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200720 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100721 } else if (strcmp(node->ns->value, LY_NSYIN)) {
722 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100723 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Michal Vasko53b7da02018-02-13 15:28:42 +0100724 LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci9b15fea2017-01-23 11:31:43 +0100725 goto error;
726 }
727 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200728 if (p_ != -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100729 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +0200730 type->info.bits.count = i + 1;
731 goto error;
732 }
733
Michal Vasko53b7da02018-02-13 15:28:42 +0100734 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200735 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200736
737 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200738 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100739 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200740 type->info.bits.count = i + 1;
741 goto error;
742 }
743 type->info.bits.bit[i].pos = (uint32_t)p_;
744
Radek Krejcie663e012016-08-01 17:12:34 +0200745 if (!dertype->der) { /* directly derived type from bits built-in type */
746 /* keep the highest enum value for automatic increment */
747 if (type->info.bits.bit[i].pos >= p) {
748 p = type->info.bits.bit[i].pos;
749 p++;
750 } else {
751 /* check that the value is unique */
752 for (j = 0; j < i; j++) {
753 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100754 LOGVAL(ctx, LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +0200755 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
756 type->info.bits.bit[j].name);
757 type->info.bits.count = i + 1;
758 goto error;
759 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200760 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200761 }
762 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200763
Radek Krejci8d6b7422017-02-03 14:42:13 +0100764 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100765 LYEXT_SUBSTMT_POSITION, 0, unres)) {
766 goto error;
767 }
PavolVican92f23622017-12-12 13:35:56 +0100768
PavolVican0144fae2018-02-05 15:54:17 +0100769 for (j = 0; j < type->info.bits.bit[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100770 /* set flag, which represent LYEXT_OPT_VALID */
771 if (type->info.bits.bit[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100772 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100773 break;
774 }
775 }
776
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200777 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100778 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, type->info.bits.bit[i].iffeature_size, "if-features", "bit", error);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200779 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200780 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100781 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200782 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200783 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200784 }
Radek Krejcie663e012016-08-01 17:12:34 +0200785
786 if (!dertype->der) { /* directly derived type from bits built-in type */
787 if (p_ == -1) {
788 /* assign value automatically */
789 if (p > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100790 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejcie663e012016-08-01 17:12:34 +0200791 type->info.bits.count = i + 1;
792 goto error;
793 }
794 type->info.bits.bit[i].pos = (uint32_t)p;
795 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
796 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200797 }
Radek Krejcie663e012016-08-01 17:12:34 +0200798 } else { /* restricted bits type */
799 if (p_ == -1) {
800 /* automatically assign position from base type */
801 type->info.bits.bit[i].pos = bits_sc[j].pos;
802 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
803 } else {
804 /* check that the assigned position corresponds to the original
805 * position of the bit in the base type */
806 if (p_ != bits_sc[j].pos) {
807 /* p_ - assigned position in restricted bits
808 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100809 LOGVAL(ctx, LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200810 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200811 type->info.bits.count = i + 1;
812 goto error;
813 }
814 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200815 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200816
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200817 /* if-features */
818 if (c_ftrs) {
819 bits_sc = &type->info.bits.bit[i];
820 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
821 if (!bits_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100822 LOGMEM(ctx);
Radek Krejci994b6f62015-06-18 16:47:27 +0200823 type->info.bits.count = i + 1;
824 goto error;
825 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200826
827 LY_TREE_FOR(next->child, node) {
828 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200829 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200830 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
831 bits_sc->iffeature_size++;
832 if (rc) {
833 type->info.bits.count = i + 1;
834 goto error;
835 }
836 }
837 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200838 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200839
840 /* keep them ordered by position */
841 j = i;
842 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
843 /* switch them */
844 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
845 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
846 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
847 j--;
848 }
Michal Vaskoc643f712018-09-14 08:26:13 +0200849
850 ++i;
Radek Krejci994b6f62015-06-18 16:47:27 +0200851 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200854 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200855 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200856 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200857
Radek Krejcif9401c32015-06-26 16:47:36 +0200858 if (!strcmp(node->name, "range")) {
859 if (type->info.dec64.range) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100860 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200861 goto error;
862 }
863
Michal Vasko53b7da02018-02-13 15:28:42 +0100864 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200865 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko53b7da02018-02-13 15:28:42 +0100866 LY_CHECK_ERR_GOTO(!type->info.dec64.range, LOGMEM(ctx), error);
867 type->info.dec64.range->expr = lydict_insert(ctx, value, 0);
Radek Krejcif9401c32015-06-26 16:47:36 +0200868
869 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100870 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200871 goto error;
872 }
PavolVican0144fae2018-02-05 15:54:17 +0100873 for (j = 0; j < type->info.dec64.range->ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100874 /* set flag, which represent LYEXT_OPT_VALID */
875 if (type->info.dec64.range->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100876 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100877 break;
878 }
879 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200880 } else if (!strcmp(node->name, "fraction-digits")) {
881 if (type->info.dec64.dig) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100882 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200883 goto error;
884 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100885 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200886 v = strtol(value, NULL, 10);
887
888 /* range check */
889 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100890 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200891 goto error;
892 }
893 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200894 type->info.dec64.div = 10;
895 for (i = 1; i < v; i++) {
896 type->info.dec64.div *= 10;
897 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100898
899 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100900 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100901 goto error;
902 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200903 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100904 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200905 goto error;
906 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200907 }
908
909 /* mandatory sub-statement(s) check */
910 if (!type->info.dec64.dig && !type->der->type.der) {
911 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vasko53b7da02018-02-13 15:28:42 +0100912 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200913 goto error;
914 }
Radek Krejci7511f402015-07-10 09:56:30 +0200915 if (type->info.dec64.dig && type->der->type.der) {
916 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vasko53b7da02018-02-13 15:28:42 +0100917 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200918 goto error;
919 }
Radek Krejci4800f652016-09-08 14:02:52 +0200920
921 /* copy fraction-digits specification from parent type for easier internal use */
922 if (type->der->type.der) {
923 type->info.dec64.dig = type->der->type.info.dec64.dig;
924 type->info.dec64.div = type->der->type.info.dec64.div;
925 }
926
Michal Vasko53b7da02018-02-13 15:28:42 +0100927 if (type->info.dec64.range && lyp_check_length_range(ctx, type->info.dec64.range->expr, type)) {
928 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200929 goto error;
930 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200931 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200933 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200934 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200935
Radek Krejci994b6f62015-06-18 16:47:27 +0200936 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939 if (!strcmp(node->name, "enum")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100940 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.enums.count, type->info.enums.count, "enums", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200941 type->info.enums.count = 0; goto error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200943 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100944 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200945 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200946 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 }
948 }
Radek Krejcie663e012016-08-01 17:12:34 +0200949 dertype = &type->der->type;
950 if (!dertype->der) {
951 if (!type->info.enums.count) {
952 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100953 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200954 goto error;
955 }
956 } else {
957 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
958 if (module->version < 2 && type->info.enums.count) {
959 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
960 * 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 +0100961 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200962 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200963 goto error;
964 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200965 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200966
Radek Krejci1574a8d2015-08-03 14:16:52 +0200967 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +0100968 LY_CHECK_ERR_GOTO(!type->info.enums.enm, LOGMEM(ctx), error);
Radek Krejcifc8d8322016-06-24 11:23:23 +0200969
Radek Krejcie663e012016-08-01 17:12:34 +0200970 v = 0;
Michal Vaskoc643f712018-09-14 08:26:13 +0200971 i = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200972 LY_TREE_FOR(yin->child, next) {
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200973 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200974
Michal Vasko53b7da02018-02-13 15:28:42 +0100975 GETVAL(ctx, value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100976 if (!value[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100977 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
978 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100979 goto error;
980 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100981 type->info.enums.enm[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100982 if (read_yin_common(module, NULL, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, next, 0, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 type->info.enums.count = i + 1;
984 goto error;
985 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200988 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100990 LOGVAL(ctx, LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 type->info.enums.count = i + 1;
992 goto error;
993 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200994
Radek Krejcie663e012016-08-01 17:12:34 +0200995 if (!dertype->der) { /* directly derived type from enumeration built-in type */
996 /* check the name uniqueness */
997 for (j = 0; j < i; j++) {
998 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100999 LOGVAL(ctx, LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
Radek Krejcie663e012016-08-01 17:12:34 +02001000 type->info.enums.count = i + 1;
1001 goto error;
1002 }
1003 }
1004 } else {
1005 /* restricted enumeration type - the name MUST be used in the base type */
1006 enms_sc = dertype->info.enums.enm;
1007 for (j = 0; j < dertype->info.enums.count; j++) {
1008 if (ly_strequal(enms_sc[j].name, value, 1)) {
1009 break;
1010 }
1011 }
1012 if (j == dertype->info.enums.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001013 LOGVAL(ctx, LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001014 type->info.enums.count = i + 1;
1015 goto error;
1016 }
1017 }
Radek Krejci04581c62015-05-22 21:24:00 +02001018
Radek Krejcie663e012016-08-01 17:12:34 +02001019 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001020 LY_TREE_FOR_SAFE(next->child, next2, node) {
1021 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001022 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001023 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +01001024 } else if (strcmp(node->ns->value, LY_NSYIN)) {
1025 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001026 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001027 LYEXT_SUBSTMT_SELF, 0, unres)) {
1028 goto error;
1029 }
1030 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +02001031 if (val_set) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001032 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +02001033 type->info.enums.count = i + 1;
1034 goto error;
1035 }
1036
Michal Vasko53b7da02018-02-13 15:28:42 +01001037 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +02001038 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +02001039
1040 /* range check */
1041 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001042 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +02001043 type->info.enums.count = i + 1;
1044 goto error;
1045 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001046 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +02001047
Radek Krejcie663e012016-08-01 17:12:34 +02001048 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001049 if (!i) {
1050 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001051 v = type->info.enums.enm[i].value;
1052 v++;
1053 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001054 /* keep the highest enum value for automatic increment */
1055 if (type->info.enums.enm[i].value >= v) {
1056 v = type->info.enums.enm[i].value;
1057 v++;
1058 } else {
1059 /* check that the value is unique */
1060 for (j = 0; j < i; j++) {
1061 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001062 LOGVAL(ctx, LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican5de389c2016-08-30 08:55:15 +02001063 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1064 type->info.enums.enm[j].name);
1065 type->info.enums.count = i + 1;
1066 goto error;
1067 }
Radek Krejcie663e012016-08-01 17:12:34 +02001068 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001069 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070 }
1071 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001072 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001073
Radek Krejci8d6b7422017-02-03 14:42:13 +01001074 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001075 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1076 goto error;
1077 }
PavolVican92f23622017-12-12 13:35:56 +01001078
PavolVican0144fae2018-02-05 15:54:17 +01001079 for (j = 0; j < type->info.enums.enm[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +01001080 /* set flag, which represent LYEXT_OPT_VALID */
1081 if (type->info.enums.enm[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001082 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001083 break;
1084 }
1085 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001086 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001087 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, type->info.enums.enm[i].iffeature_size, "if-features", "enum", error);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001088 c_ftrs++;
1089
Radek Krejci0d70c372015-07-02 16:23:10 +02001090 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001091 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001092 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001094 }
Radek Krejcie663e012016-08-01 17:12:34 +02001095
1096 if (!dertype->der) { /* directly derived type from enumeration */
1097 if (!val_set) {
1098 /* assign value automatically */
1099 if (v > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001100 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejcie663e012016-08-01 17:12:34 +02001101 type->info.enums.count = i + 1;
1102 goto error;
1103 }
1104 type->info.enums.enm[i].value = v;
1105 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1106 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 }
Radek Krejcie663e012016-08-01 17:12:34 +02001108 } else { /* restricted enum type */
1109 if (!val_set) {
1110 /* automatically assign value from base type */
1111 type->info.enums.enm[i].value = enms_sc[j].value;
1112 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1113 } else {
1114 /* check that the assigned value corresponds to the original
1115 * value of the enum in the base type */
1116 if (v_ != enms_sc[j].value) {
1117 /* v_ - assigned value in restricted enum
1118 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001119 LOGVAL(ctx, LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001120 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001121 type->info.enums.count = i + 1;
1122 goto error;
1123 }
1124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001126
1127 /* if-features */
1128 if (c_ftrs) {
1129 enms_sc = &type->info.enums.enm[i];
1130 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1131 if (!enms_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001132 LOGMEM(ctx);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 type->info.enums.count = i + 1;
1134 goto error;
1135 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001136
1137 LY_TREE_FOR(next->child, node) {
1138 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001139 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001140 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1141 enms_sc->iffeature_size++;
1142 if (rc) {
1143 type->info.enums.count = i + 1;
1144 goto error;
1145 }
1146 }
1147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001149
Michal Vaskoc643f712018-09-14 08:26:13 +02001150 ++i;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151 }
1152 break;
1153
1154 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001155 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001156
Michal Vaskof2d43962016-09-02 11:10:16 +02001157 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001158 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001159
Michal Vaskoe29c6622015-11-27 15:02:31 +01001160 if (strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001161 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001162 goto error;
1163 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001164
Michal Vasko53b7da02018-02-13 15:28:42 +01001165 GETVAL(ctx, value, yin->child, "name");
Michal Vaskof2d43962016-09-02 11:10:16 +02001166 /* store in the JSON format */
1167 value = transform_schema2json(module, value);
1168 if (!value) {
1169 goto error;
1170 }
1171 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Michal Vasko53b7da02018-02-13 15:28:42 +01001172 lydict_remove(ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001173 if (rc == -1) {
1174 goto error;
1175 }
Radek Krejci18a44882017-01-23 13:47:29 +01001176
Radek Krejci8d6b7422017-02-03 14:42:13 +01001177 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001178 goto error;
1179 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001180 }
1181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001182 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001183 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001184 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001185 break;
1186 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001187 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001188 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001189 } else {
1190 if (type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001191 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
Pavol Vicanf0046f42016-09-07 15:11:09 +02001192 goto error;
1193 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 if (yin->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001196 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001197 goto error;
1198 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001199 break;
1200
1201 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001202 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001203 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001204
Radek Krejciaf351422015-06-19 14:49:38 +02001205 if (!strcmp(node->name, "require-instance")) {
1206 if (type->info.inst.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001207 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001208 goto error;
1209 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001210 GETVAL(ctx, value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001211 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001212 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001213 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001214 type->info.inst.req = -1;
1215 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001216 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001217 goto error;
1218 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001219
1220 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001221 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001222 goto error;
1223 }
Radek Krejciaf351422015-06-19 14:49:38 +02001224 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001225 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001226 goto error;
1227 }
Radek Krejciaf351422015-06-19 14:49:38 +02001228 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001230 break;
1231
Radek Krejcif2860132015-06-20 12:37:20 +02001232 case LY_TYPE_BINARY:
1233 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 case LY_TYPE_INT8:
1235 case LY_TYPE_INT16:
1236 case LY_TYPE_INT32:
1237 case LY_TYPE_INT64:
1238 case LY_TYPE_UINT8:
1239 case LY_TYPE_UINT16:
1240 case LY_TYPE_UINT32:
1241 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001242 /* RFC 6020 9.2.4 - range */
1243
1244 /* length and range are actually the same restriction, so process
1245 * them by this common code, we just need to differ the name and
1246 * structure where the information will be stored
1247 */
1248 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001249 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001250 name = "length";
1251 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001252 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001253 name = "range";
1254 }
1255
Radek Krejci73adb602015-07-02 18:07:40 +02001256 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001257
Radek Krejcif2860132015-06-20 12:37:20 +02001258 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001259 if (*restrs) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001260 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001261 goto error;
1262 }
1263
Michal Vasko53b7da02018-02-13 15:28:42 +01001264 GETVAL(ctx, value, node, "value");
1265 if (lyp_check_length_range(ctx, value, type)) {
1266 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001267 goto error;
1268 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001269 *restrs = calloc(1, sizeof **restrs);
Michal Vasko53b7da02018-02-13 15:28:42 +01001270 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM(ctx), error);
1271 (*restrs)->expr = lydict_insert(ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001272
1273 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001274 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001275 goto error;
1276 }
PavolVican92f23622017-12-12 13:35:56 +01001277
1278 for (j = 0; j < (*restrs)->ext_size; ++j) {
1279 /* set flag, which represent LYEXT_OPT_VALID */
1280 if ((*restrs)->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001281 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001282 break;
1283 }
1284 }
Radek Krejcif2860132015-06-20 12:37:20 +02001285 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001286 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001287 goto error;
1288 }
Radek Krejcif2860132015-06-20 12:37:20 +02001289 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001290 break;
1291
1292 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001293 /* flag resolving for later use */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001294 if (!parenttype) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001295 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1296 if (siter) {
1297 /* just a flag - do not resolve */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001298 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001299 }
1300 }
1301
Radek Krejcidc4c1412015-06-19 15:39:54 +02001302 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001303 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001304
Michal Vasko88c29542015-11-27 14:57:53 +01001305 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001306 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001307 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001308 goto error;
1309 }
1310
Michal Vasko53b7da02018-02-13 15:28:42 +01001311 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001312 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001313 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001314 if (!type->info.lref.path) {
1315 goto error;
1316 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001317
1318 /* try to resolve leafref path only when this is instantiated
1319 * leaf, so it is not:
1320 * - typedef's type,
1321 * - in grouping definition,
1322 * - just instantiated in a grouping definition,
1323 * because in those cases the nodes referenced in path might not be present
1324 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001325 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001326 goto error;
1327 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001328
1329 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001330 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001331 goto error;
1332 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001333 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001334 if (type->info.lref.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001335 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001336 goto error;
1337 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001338 GETVAL(ctx, value, node, "value");
Michal Vasko08ae53e2016-09-02 12:40:04 +02001339 if (!strcmp(value, "true")) {
1340 type->info.lref.req = 1;
1341 } else if (!strcmp(value, "false")) {
1342 type->info.lref.req = -1;
1343 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001344 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Michal Vasko08ae53e2016-09-02 12:40:04 +02001345 goto error;
1346 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001347
1348 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001349 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001350 goto error;
1351 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001352 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001353 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001354 goto error;
1355 }
Radek Krejci73adb602015-07-02 18:07:40 +02001356 }
1357
Radek Krejci742be352016-07-17 12:18:54 +02001358 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001359 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001360 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001361 goto error;
1362 } else {
1363 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001364 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001365 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001366 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001367 goto error;
1368 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001369 }
Radek Krejci742be352016-07-17 12:18:54 +02001370 }
1371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001372 break;
1373
1374 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001375 /* RFC 6020 9.4.4 - length */
1376 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001377 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001378 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001379
Radek Krejci3733a802015-06-19 13:43:21 +02001380 if (!strcmp(node->name, "length")) {
1381 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001382 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001383 goto error;
1384 }
1385
Michal Vasko53b7da02018-02-13 15:28:42 +01001386 GETVAL(ctx, value, node, "value");
1387 if (lyp_check_length_range(ctx, value, type)) {
1388 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001389 goto error;
1390 }
1391 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001392 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1393 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001394
Radek Krejci5fbc9162015-06-19 14:11:11 +02001395 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001396 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001397 goto error;
1398 }
PavolVican92f23622017-12-12 13:35:56 +01001399
1400 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1401 /* set flag, which represent LYEXT_OPT_VALID */
1402 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001403 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001404 break;
1405 }
1406 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001407 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001408 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001409 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001410 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001411 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001412 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001413 goto error;
1414 }
1415 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001416 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001417 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001418 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001419 in_grp = 1;
1420 }
Radek Krejci73adb602015-07-02 18:07:40 +02001421 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001422 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001423#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001424 if (!in_grp) {
1425 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001426 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001427 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001428 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001429#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001430 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001431 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001432
Michal Vasko9c7dee32018-07-09 09:12:59 +02001433 if (in_grp) {
1434 /* in grouping, just check the pattern syntax */
1435 if (!(ctx->models.flags & LY_CTX_TRUSTED) && lyp_check_pattern(ctx, value, NULL)) {
1436 goto error;
Radek Krejcib53154b2017-07-19 09:14:13 +02001437 }
Michal Vasko69068852015-07-13 14:34:31 +02001438 }
Michal Vasko9c7dee32018-07-09 09:12:59 +02001439#ifdef LY_ENABLED_CACHE
1440 else {
1441 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
1442 if (lyp_precompile_pattern(ctx, value,
1443 (pcre **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1444 (pcre_extra **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1445 goto error;
1446 }
1447 }
1448#endif
Radek Krejcifccd1442017-01-16 10:26:57 +01001449 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001450 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001451
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001452 modifier = 0x06; /* ACK */
1453 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001454 if (module->version >= 2) {
1455 LY_TREE_FOR_SAFE(node->child, next2, child) {
1456 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1457 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001458 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001459 goto error;
1460 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001461
Michal Vasko53b7da02018-02-13 15:28:42 +01001462 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001463 if (!strcmp(name, "invert-match")) {
1464 modifier = 0x15; /* NACK */
1465 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001466 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001467 goto error;
1468 }
1469 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001470 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001471 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1472 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001473 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001474
Michal Vasko53b7da02018-02-13 15:28:42 +01001475 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001476 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001477 }
1478 }
1479
1480 len = strlen(value);
1481 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001482 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001483 buf[0] = modifier;
1484 strcpy(&buf[1], value);
1485
Michal Vasko53b7da02018-02-13 15:28:42 +01001486 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001487
1488 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001489 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001490 goto error;
1491 }
PavolVican92f23622017-12-12 13:35:56 +01001492
1493 for (j = 0; j < restr->ext_size; ++j) {
1494 /* set flag, which represent LYEXT_OPT_VALID */
1495 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001496 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001497 break;
1498 }
1499 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001500 }
1501 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001502 break;
1503
1504 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001505 /* RFC 6020 7.4 - type */
1506 /* count number of types in union */
1507 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001508 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001509
Radek Krejcie4c366b2015-07-02 10:11:31 +02001510 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001511 if (type->der->type.der) {
1512 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001513 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001514 goto error;
1515 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001516 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001517 i++;
1518 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001519 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001520 goto error;
1521 }
1522 }
1523
Radek Krejci038d5d92016-09-12 15:07:15 +02001524 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001525 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001526 goto error;
1527 }
1528
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001529 /* inherit instid presence information */
1530 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1531 type->info.uni.has_ptr_type = 1;
1532 }
1533
Radek Krejcie4c366b2015-07-02 10:11:31 +02001534 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001535 if (i) {
1536 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001537 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001538 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001539
Radek Krejcie4c366b2015-07-02 10:11:31 +02001540 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001541 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001542 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001543 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001544 if (!rc) {
1545 type->info.uni.count++;
1546
Radek Krejci7de36cf2016-09-12 16:18:50 +02001547 if (module->version < 2) {
1548 /* union's type cannot be empty or leafref */
1549 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001550 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001551 rc = -1;
1552 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001553 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001554 rc = -1;
1555 }
Michal Vasko88c29542015-11-27 14:57:53 +01001556 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001557
1558 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001559 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1560 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1561 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001562 type->info.uni.has_ptr_type = 1;
1563 }
Michal Vasko88c29542015-11-27 14:57:53 +01001564 }
1565 if (rc) {
1566 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1567 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001568 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001569 }
1570 free(type->info.uni.types);
1571 type->info.uni.types = NULL;
1572 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001573 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001574 type->der = NULL;
1575 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001576
1577 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001578 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001579 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001580 goto error;
1581 }
Michal Vasko88c29542015-11-27 14:57:53 +01001582 }
1583 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001584
Michal Vasko88c29542015-11-27 14:57:53 +01001585 case LY_TYPE_BOOL:
1586 case LY_TYPE_EMPTY:
1587 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001588 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001589 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001590 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 break;
1593
1594 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001595 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001596 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 }
1598
PavolVican92f23622017-12-12 13:35:56 +01001599 for(j = 0; j < type->ext_size; ++j) {
1600 /* set flag, which represent LYEXT_OPT_VALID */
1601 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001602 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001603 break;
1604 }
1605 }
1606
1607 /* if derived type has extension, which need validate data */
1608 dertype = &type->der->type;
1609 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001610 if (dertype->parent->flags & LYS_VALID_EXT) {
1611 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001612 }
1613 dertype = &dertype->der->type;
1614 }
1615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001617
1618error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001619 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001620 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001621}
1622
Michal Vasko0d343d12015-08-24 14:57:36 +02001623/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001625fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1626 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001627{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001629 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001630 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001631 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001632 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001633
Michal Vasko53b7da02018-02-13 15:28:42 +01001634 GETVAL(ctx, value, yin, "name");
1635 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 goto error;
1637 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001638 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001641 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 goto error;
1643 }
Radek Krejcieac35532015-05-31 19:09:15 +02001644
Michal Vasko88c29542015-11-27 14:57:53 +01001645 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001646 if (strcmp(node->ns->value, LY_NSYIN)) {
1647 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001648 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001649 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001650 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001651 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001652 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001653 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 goto error;
1655 }
Michal Vasko88c29542015-11-27 14:57:53 +01001656 /* HACK for unres */
1657 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001658 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001659 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001660 goto error;
1661 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001662 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001663
Radek Krejci07d0fb92017-01-13 14:11:05 +01001664 /* skip lyxml_free() at the end of the loop, node was freed or at least unlinked in unres processing */
Radek Krejcie534c132016-11-23 13:32:31 +01001665 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 } else if (!strcmp(node->name, "default")) {
1667 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001668 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001669 goto error;
1670 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001671 GETVAL(ctx, value, node, "value");
1672 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001673
Radek Krejci8d6b7422017-02-03 14:42:13 +01001674 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001675 goto error;
1676 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 } else if (!strcmp(node->name, "units")) {
1678 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001679 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 goto error;
1681 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001682 GETVAL(ctx, value, node, "name");
1683 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001684
Radek Krejci8d6b7422017-02-03 14:42:13 +01001685 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001686 goto error;
1687 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001689 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 goto error;
1691 }
Radek Krejcie534c132016-11-23 13:32:31 +01001692
Michal Vasko53b7da02018-02-13 15:28:42 +01001693 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001697 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001698 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001699 goto error;
1700 }
Radek Krejcieac35532015-05-31 19:09:15 +02001701
Michal Vasko478c4652016-07-21 12:55:01 +02001702 /* check default value (if not defined, there still could be some restrictions
1703 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001704 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001705 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001706 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001707 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001708
Radek Krejcie534c132016-11-23 13:32:31 +01001709 /* finish extensions parsing */
1710 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001711 /* some extensions may be already present from the substatements */
1712 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001713 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001714 tpdf->ext = reallocated;
1715
1716 /* init memory */
1717 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1718
Radek Krejcie534c132016-11-23 13:32:31 +01001719 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001720 rc = lyp_yin_fill_ext(tpdf, LYEXT_PAR_TYPE, 0, 0, module, node, &tpdf->ext, tpdf->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001721 tpdf->ext_size++;
1722 if (rc) {
1723 goto error;
1724 }
1725 }
1726 }
1727
PavolVican92f23622017-12-12 13:35:56 +01001728 for (i = 0; i < tpdf->ext_size; ++i) {
1729 /* set flag, which represent LYEXT_OPT_VALID */
1730 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001731 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001732 break;
1733 }
1734 }
1735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001737
1738error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001739 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001740}
1741
Radek Krejcia1a6b762016-11-14 09:53:38 +09001742static int
Radek Krejcie534c132016-11-23 13:32:31 +01001743fill_yin_extension(struct lys_module *module, struct lyxml_elem *yin, struct lys_ext *ext, struct unres_schema *unres)
Radek Krejcia1a6b762016-11-14 09:53:38 +09001744{
Michal Vasko53b7da02018-02-13 15:28:42 +01001745 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001746 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001747 struct lyxml_elem *child, *node, *next, *next2;
1748 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001749 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001750
Michal Vasko53b7da02018-02-13 15:28:42 +01001751 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001752
Michal Vasko53b7da02018-02-13 15:28:42 +01001753 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001754 goto error;
1755 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001756 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001757
Radek Krejci07d0fb92017-01-13 14:11:05 +01001758 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001759 goto error;
1760 }
1761
Radek Krejcie534c132016-11-23 13:32:31 +01001762 LY_TREE_FOR_SAFE(yin->child, next, node) {
1763 if (strcmp(node->ns->value, LY_NSYIN)) {
1764 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001765 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001766 c_ext++;
1767 } else if (!strcmp(node->name, "argument")) {
1768 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001769 GETVAL(ctx, value, node, "name");
1770 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001771 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001772 goto error;
1773 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001774
Radek Krejcia1a6b762016-11-14 09:53:38 +09001775 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001776 LY_TREE_FOR_SAFE(node->child, next2, child) {
1777 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001778 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001779 if (ly_strequal(value, "true", 0)) {
1780 ext->flags |= LYS_YINELEM;
1781 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001782
Radek Krejci8d6b7422017-02-03 14:42:13 +01001783 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001784 goto error;
1785 }
Radek Krejcie534c132016-11-23 13:32:31 +01001786 } else if (child->ns) {
1787 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001788 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001789 goto error;
1790 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001791 }
1792
Michal Vasko53b7da02018-02-13 15:28:42 +01001793 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001794 } else {
1795 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001796 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001797 goto error;
1798 }
1799 }
1800
1801 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001802 /* some extensions may be already present from the substatements */
1803 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001804 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001805 ext->ext = reallocated;
1806
1807 /* init memory */
1808 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1809
1810 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001811 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001812 rc = lyp_yin_fill_ext(ext, LYEXT_PAR_EXT, 0, 0, module, node, &ext->ext, ext->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001813 ext->ext_size++;
1814 if (rc) {
1815 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001816 }
1817 }
1818 }
1819
Radek Krejci0a498f82017-01-04 16:24:15 +01001820 /* search for plugin */
1821 ext->plugin = ext_get_plugin(ext->name, ext->module->name, ext->module->rev ? ext->module->rev[0].date : NULL);
Radek Krejcia1a6b762016-11-14 09:53:38 +09001822
1823 return EXIT_SUCCESS;
1824
1825error:
1826 return EXIT_FAILURE;
1827}
1828
Michal Vasko0d343d12015-08-24 14:57:36 +02001829/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001830static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001831fill_yin_feature(struct lys_module *module, struct lyxml_elem *yin, struct lys_feature *f, struct unres_schema *unres)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001832{
Michal Vasko53b7da02018-02-13 15:28:42 +01001833 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001834 const char *value;
1835 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001836 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001837 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001838
Michal Vasko53b7da02018-02-13 15:28:42 +01001839 GETVAL(ctx, value, yin, "name");
1840 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001841 goto error;
1842 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001843 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001844 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001845
Radek Krejci07d0fb92017-01-13 14:11:05 +01001846 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001847 goto error;
1848 }
1849
Radek Krejcie534c132016-11-23 13:32:31 +01001850 LY_TREE_FOR(yin->child, child) {
1851 if (strcmp(child->ns->value, LY_NSYIN)) {
1852 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001853 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001854 c_ext++;
1855 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001856 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001857 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001858 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001859 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001860 goto error;
1861 }
1862 }
1863
Radek Krejcie534c132016-11-23 13:32:31 +01001864 if (c_ftrs) {
1865 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001866 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001867 }
Radek Krejcie534c132016-11-23 13:32:31 +01001868 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001869 /* some extensions may be already present from the substatements */
1870 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001871 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001872 f->ext = reallocated;
1873
1874 /* init memory */
1875 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001876 }
1877
Radek Krejcie534c132016-11-23 13:32:31 +01001878 LY_TREE_FOR_SAFE(yin->child, next, child) {
1879 if (strcmp(child->ns->value, LY_NSYIN)) {
1880 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001881 ret = lyp_yin_fill_ext(f, LYEXT_PAR_FEATURE, 0, 0, module, child, &f->ext, f->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001882 f->ext_size++;
1883 if (ret) {
1884 goto error;
1885 }
1886 } else { /* if-feature */
1887 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1888 f->iffeature_size++;
1889 if (ret) {
1890 goto error;
1891 }
1892 }
1893 }
1894
Radek Krejcic79c6b12016-07-26 15:11:49 +02001895 /* check for circular dependencies */
1896 if (f->iffeature_size) {
1897 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1898 goto error;
1899 }
1900 }
1901
Radek Krejci3cf9e222015-06-18 11:37:50 +02001902 return EXIT_SUCCESS;
1903
1904error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001905 return EXIT_FAILURE;
1906}
1907
Michal Vasko0d343d12015-08-24 14:57:36 +02001908/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001909static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001910fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must, struct unres_schema *unres)
Radek Krejci800af702015-06-02 13:46:01 +02001911{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001912 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001913
Michal Vasko53b7da02018-02-13 15:28:42 +01001914 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001915 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001916 if (!must->expr) {
1917 goto error;
1918 }
Radek Krejci800af702015-06-02 13:46:01 +02001919
Radek Krejciaa9c5202017-02-15 16:10:14 +01001920 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001921
Michal Vasko77dc5652016-02-15 12:32:42 +01001922error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001923 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001924}
1925
Radek Krejci581ce772015-11-10 17:22:40 +01001926static int
Radek Krejci7417a082017-02-16 11:07:59 +01001927fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1928 struct unres_schema *unres)
1929{
Michal Vasko53b7da02018-02-13 15:28:42 +01001930 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001931 struct lyxml_elem *next, *child;
1932 const char *value;
1933
Michal Vasko53b7da02018-02-13 15:28:42 +01001934 GETVAL(ctx, value, yin, "date");
1935 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001936 goto error;
1937 }
1938 memcpy(rev->date, value, LY_REV_SIZE - 1);
1939
1940 LY_TREE_FOR_SAFE(yin->child, next, child) {
1941 if (!child->ns) {
1942 /* garbage */
1943 continue;
1944 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1945 /* possible extension instance */
1946 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1947 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1948 goto error;
1949 }
1950 } else if (!strcmp(child->name, "description")) {
1951 if (rev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001952 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001953 goto error;
1954 }
1955 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1956 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1957 goto error;
1958 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001959 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001960 if (!rev->dsc) {
1961 goto error;
1962 }
1963 } else if (!strcmp(child->name, "reference")) {
1964 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001965 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001966 goto error;
1967 }
1968 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1969 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1970 goto error;
1971 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001972 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001973 if (!rev->ref) {
1974 goto error;
1975 }
1976 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001977 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001978 goto error;
1979 }
1980 }
1981
1982 return EXIT_SUCCESS;
1983
1984error:
1985 return EXIT_FAILURE;
1986}
1987
1988static int
Michal Vasko88c29542015-11-27 14:57:53 +01001989fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1990 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001991{
Michal Vasko53b7da02018-02-13 15:28:42 +01001992 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02001993 int i, j, ret = EXIT_FAILURE;
1994 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02001995 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001996 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001997
1998 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01001999 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01002000
2001 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002002 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01002003 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002004 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002005 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02002006 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01002007 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01002008 while (isspace(*vaux)) {
2009 vaux++;
2010 }
2011 }
2012 unique->expr_size++;
2013 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002014 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01002015
2016 for (i = 0; i < unique->expr_size; i++) {
2017 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02002018 if (vaux) {
2019 c = *vaux;
2020 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01002021 }
2022
2023 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02002024 unique->expr[i] = transform_schema2json(module, value);
2025 if (vaux) {
2026 *vaux = c;
2027 }
Radek Krejci581ce772015-11-10 17:22:40 +01002028
2029 /* check that the expression does not repeat */
2030 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002031 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002032 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
2033 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01002034 goto error;
2035 }
2036 }
2037
2038 /* try to resolve leaf */
2039 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002040 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01002041 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02002042 unique_info->list = parent;
2043 unique_info->expr = unique->expr[i];
2044 unique_info->trg_type = &unique->trg_type;
2045 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02002046 goto error;
2047 }
Radek Krejci581ce772015-11-10 17:22:40 +01002048 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02002049 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002050 goto error;
2051 }
2052 }
2053
2054 /* move to next token */
2055 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002056 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002057 value++;
2058 }
2059 }
2060
Radek Krejci1a9c3612017-04-24 14:49:43 +02002061 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002062
2063error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002064 free(start);
2065 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002066}
2067
Michal Vasko0d343d12015-08-24 14:57:36 +02002068/* logs directly
2069 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002070 * type: 0 - min, 1 - max
2071 */
2072static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002073deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002074{
2075 const char *value;
2076 char *endptr;
2077 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002078 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002079 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002080
Michal Vaskof7e57d52016-03-07 11:31:09 +01002081 /* del min/max is forbidden */
2082 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002083 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002084 goto error;
2085 }
2086
Radek Krejcieb00f512015-07-01 16:44:58 +02002087 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002088 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002089 max = &((struct lys_node_leaflist *)target)->max;
2090 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002091 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002092 max = &((struct lys_node_list *)target)->max;
2093 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002094 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002095 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2096 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002097 goto error;
2098 }
2099
Michal Vasko53b7da02018-02-13 15:28:42 +01002100 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002101 while (isspace(value[0])) {
2102 value++;
2103 }
2104
Radek Krejci0d7b2472016-02-12 11:11:03 +01002105 if (type && !strcmp(value, "unbounded")) {
2106 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002107 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002108 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002109 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002110 /* convert it to uint32_t */
2111 errno = 0;
2112 endptr = NULL;
2113 val = strtoul(value, &endptr, 10);
2114 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002115 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002116 goto error;
2117 }
2118 if (type) {
2119 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002120 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002121 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002122 } else {
2123 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002124 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002125 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002126 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002127 }
2128
2129 if (d->mod == LY_DEVIATE_ADD) {
2130 /* check that there is no current value */
2131 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002132 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2133 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002134 goto error;
2135 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002136 } else if (d->mod == LY_DEVIATE_RPL) {
2137 /* unfortunately, there is no way to check reliably that there
2138 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002139 }
2140
Michal Vaskof7e57d52016-03-07 11:31:09 +01002141 /* add (already checked) and replace */
2142 /* set new value specified in deviation */
2143 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002144
Pavol Vican09adcc32016-08-25 10:51:36 +02002145 /* check min-elements is smaller than max-elements */
2146 if (*max && *min > *max) {
2147 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002148 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2149 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002150 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002151 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2152 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002153 }
2154 goto error;
2155 }
2156
Radek Krejcieb00f512015-07-01 16:44:58 +02002157 return EXIT_SUCCESS;
2158
2159error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002160 return EXIT_FAILURE;
2161}
2162
Michal Vasko0d343d12015-08-24 14:57:36 +02002163/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002164static int
Michal Vasko88c29542015-11-27 14:57:53 +01002165fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2166 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002167{
2168 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002169 struct lyxml_elem *next, *next2, *child, *develem;
2170 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002171 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002172 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002173 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002174 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002175 struct lys_deviate *d = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002176 struct lys_node *node, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002177 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002178 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002179 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002180 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002181 struct lys_node_leaflist *llist = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002182 struct lys_node_inout *inout;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002183 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002184 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002185 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002186 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002187 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002188 void *reallocated;
Andrew Langefeldf9763242018-09-16 22:23:50 -05002189 size_t deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002190
Michal Vasko53b7da02018-02-13 15:28:42 +01002191 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002192 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002193 if (!dev->target_name) {
2194 goto error;
2195 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002196
2197 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002198 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2199 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002200 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002201 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002202 goto error;
2203 }
Michal Vasko50576712017-07-28 12:28:33 +02002204 dev_target = set->set.s[0];
2205 ly_set_free(set);
2206
Radek Krejcic4283442016-04-22 09:19:27 +02002207 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002208 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2209 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002210 goto error;
2211 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002212
2213 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002214 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002215 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002216 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002217 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002218 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2219 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002220 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002221 c_ext++;
2222 continue;
2223 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002224 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002225 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002226 goto error;
2227 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002228 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002229 goto error;
2230 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002231 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002232 if (!dev->dsc) {
2233 goto error;
2234 }
2235 } else if (!strcmp(child->name, "reference")) {
2236 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002237 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002238 goto error;
2239 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002240 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002241 goto error;
2242 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002243 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002244 if (!dev->ref) {
2245 goto error;
2246 }
2247 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002248 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002249 c_dev++;
2250
Michal Vasko345da0a2015-12-02 10:35:55 +01002251 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002252 * further processed later
2253 */
2254 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002255
Radek Krejcieb00f512015-07-01 16:44:58 +02002256 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002257 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002258 goto error;
2259 }
2260
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002261 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002262 }
2263
2264 if (c_dev) {
2265 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002266 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002267 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002268 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002269 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002270 }
Radek Krejcie534c132016-11-23 13:32:31 +01002271 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002272 /* some extensions may be already present from the substatements */
2273 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002274 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002275 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002276
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002277 /* init memory */
2278 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2279 }
Radek Krejcie534c132016-11-23 13:32:31 +01002280
2281 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2282 if (strcmp(develem->ns->value, LY_NSYIN)) {
2283 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002284 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 +01002285 dev->ext_size++;
2286 if (rc) {
2287 goto error;
2288 }
2289 continue;
2290 }
2291
2292 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002293 /* init */
2294 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002295 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002296 c_must = 0;
2297 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002298 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002299 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002300
2301 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002302 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002303 if (!strcmp(value, "not-supported")) {
2304 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002305 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002306 * not-supported deviation must be the only deviation of the target
2307 */
2308 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002309 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2310 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 +02002311 goto error;
2312 }
2313
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002314 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002315 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2316 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2317 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002318 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2319 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002320 goto error;
2321 }
2322 }
2323 }
Radek Krejci5b917642015-07-02 09:03:13 +02002324
Michal Vaskoff006c12016-02-17 11:15:19 +01002325 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002326 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002327 lys_node_unlink(dev_target);
Michal Vasko5df038e2018-08-02 09:41:26 +02002328 if (parent) {
2329 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
2330 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2331 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2332 * path), so we need to remember the augment as an addition */
2333 /* remember uses parent so we can reconnect to it */
2334 dev_target->parent = parent;
2335 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
2336 /* re-create implicit node */
2337 inout = calloc(1, sizeof *inout);
2338 LY_CHECK_ERR_GOTO(!inout, LOGMEM(ctx), error);
2339
2340 inout->nodetype = dev_target->nodetype;
2341 inout->name = lydict_insert(ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
2342 inout->module = dev_target->module;
2343 inout->flags = LYS_IMPLICIT;
2344
2345 /* insert it manually */
2346 assert(parent->child && !parent->child->next
2347 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
2348 parent->child->next = (struct lys_node *)inout;
2349 inout->prev = parent->child;
2350 parent->child->prev = (struct lys_node *)inout;
2351 inout->parent = parent;
2352 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01002353 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002354 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002355
Radek Krejcieb00f512015-07-01 16:44:58 +02002356 } else if (!strcmp(value, "add")) {
2357 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2358 } else if (!strcmp(value, "replace")) {
2359 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2360 } else if (!strcmp(value, "delete")) {
2361 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2362 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002363 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002364 goto error;
2365 }
2366 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002367 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002368
Michal Vaskoff006c12016-02-17 11:15:19 +01002369 /* store a shallow copy of the original node */
2370 if (!dev->orig_node) {
2371 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002372 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002373 /* just to be safe */
2374 if (tmp_unres.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002375 LOGINT(ctx);
Michal Vaskoff006c12016-02-17 11:15:19 +01002376 goto error;
2377 }
2378 }
2379
Radek Krejcieb00f512015-07-01 16:44:58 +02002380 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002381 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002382 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002383 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002384 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002385 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002386 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2387 /* extensions */
Michal Vasko53b7da02018-02-13 15:28:42 +01002388 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, d->ext_size, "extensions", "deviate", error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002389 c_ext++;
2390 } else if (d->mod == LY_DEVIATE_NO) {
2391 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002392 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002393 goto error;
2394 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002395 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002396 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002397 goto error;
2398 }
2399
2400 /* for we deviate from RFC 6020 and allow config property even it is/is not
2401 * specified in the target explicitly since config property inherits. So we expect
2402 * that config is specified in every node. But for delete, we check that the value
2403 * is the same as here in deviation
2404 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002405 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002406 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002407 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002408 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002409 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002410 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002411 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002412 goto error;
2413 }
2414
2415 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002416 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002417 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002418 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002419 } else { /* add and replace are the same in this case */
2420 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002421 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002422
2423 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002424 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002425 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002426
Radek Krejci8d6b7422017-02-03 14:42:13 +01002427 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002428 goto error;
2429 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002430 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002431 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 +01002432 goto error;
2433 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002434 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002435 c_dflt++;
2436
2437 /* check target node type */
2438 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002439 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2440 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002441 goto error;
2442 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002443 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2444 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002445 goto error;
2446 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002447 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2448 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002449 goto error;
2450 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002451
Radek Krejcid5a5c282016-08-15 15:38:08 +02002452 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2453 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002454
Radek Krejcieb00f512015-07-01 16:44:58 +02002455 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002456 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002457 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002458 goto error;
2459 }
2460
2461 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002462 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002463 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2464 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002465 goto error;
2466 }
2467
Michal Vasko53b7da02018-02-13 15:28:42 +01002468 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002469 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002470 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002471 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002472 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002473 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002474 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002475 goto error;
2476 }
2477
2478 if (d->mod == LY_DEVIATE_ADD) {
2479 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002480 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002481 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2482 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002483 goto error;
2484 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002485
Radek Krejci841ec082016-04-05 13:05:17 +02002486 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002487 if (d->flags & LYS_MAND_TRUE) {
2488 if (dev_target->nodetype == LYS_CHOICE) {
2489 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002490 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2491 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002492 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2493 goto error;
2494 }
2495 } else if (dev_target->nodetype == LYS_LEAF) {
2496 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002497 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2498 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002499 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2500 goto error;
2501 }
2502 }
Radek Krejci841ec082016-04-05 13:05:17 +02002503 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002504
Michal Vasko21be1b32016-03-07 12:31:34 +01002505 dev_target->flags |= d->flags & LYS_MAND_MASK;
2506 } else if (d->mod == LY_DEVIATE_RPL) {
2507 /* check that there was a value before */
2508 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002509 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2510 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002511 goto error;
2512 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002513
Michal Vasko21be1b32016-03-07 12:31:34 +01002514 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002515 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002516 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002517 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002518 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002519 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002520 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002521
2522 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2523 for (parent = dev_target->parent;
2524 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2525 parent = parent->parent) {
2526 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2527 /* stop also on presence containers */
2528 break;
2529 }
2530 }
2531 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2532 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2533 if (lyp_check_mandatory_choice(parent)) {
2534 goto error;
2535 }
2536 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002537
Radek Krejci8d6b7422017-02-03 14:42:13 +01002538 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002539 goto error;
2540 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002541 } else if (!strcmp(child->name, "min-elements")) {
2542 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002543 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002544 goto error;
2545 }
2546 f_min = 1;
2547
Michal Vasko60f4b452016-02-12 11:02:55 +01002548 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002549 goto error;
2550 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002551 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002552 goto error;
2553 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002554 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002555 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002556 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002557 goto error;
2558 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002559 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002560
Michal Vasko60f4b452016-02-12 11:02:55 +01002561 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002562 goto error;
2563 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002564 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002565 goto error;
2566 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002567 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002568 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002569 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002570 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002571 continue;
2572 } else if (!strcmp(child->name, "type")) {
2573 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002574 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002575 goto error;
2576 }
2577
Michal Vaskof7e57d52016-03-07 11:31:09 +01002578 /* add, del type is forbidden */
2579 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002580 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002581 goto error;
2582 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002583 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002584 goto error;
2585 }
2586
Radek Krejcieb00f512015-07-01 16:44:58 +02002587 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002588 if (dev_target->nodetype == LYS_LEAF) {
2589 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002590 if (((struct lys_node_leaf *)dev_target)->dflt) {
2591 ly_set_add(dflt_check, dev_target, 0);
2592 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002593 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2594 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002595 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2596 ly_set_add(dflt_check, dev_target, 0);
2597 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002598 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002599 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2600 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002601 goto error;
2602 }
2603
Radek Krejcieb00f512015-07-01 16:44:58 +02002604 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002605 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002606 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002607 /* HACK for unres */
2608 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002609 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002610 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002611 goto error;
2612 }
2613 d->type = t;
2614 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002615 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 +01002616 goto error;
2617 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002618 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002619 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002620 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002621 continue;
2622 } else if (!strcmp(child->name, "units")) {
2623 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002624 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002625 goto error;
2626 }
2627
2628 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002629 if (dev_target->nodetype == LYS_LEAFLIST) {
2630 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2631 } else if (dev_target->nodetype == LYS_LEAF) {
2632 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002633 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002634 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2635 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002636 goto error;
2637 }
2638
2639 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002640 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002641 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002642
2643 /* apply to target */
2644 if (d->mod == LY_DEVIATE_ADD) {
2645 /* check that there is no current value */
2646 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002647 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2648 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002649 goto error;
2650 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002651
Michal Vasko21be1b32016-03-07 12:31:34 +01002652 *stritem = lydict_insert(ctx, value, 0);
2653 } else if (d->mod == LY_DEVIATE_RPL) {
2654 /* check that there was a value before */
2655 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002656 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2657 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002658 goto error;
2659 }
2660
2661 lydict_remove(ctx, *stritem);
2662 *stritem = lydict_insert(ctx, value, 0);
2663 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002664 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002665 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002666 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2667 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002668 goto error;
2669 }
2670 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002671 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002672 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002673
2674 /* remove its extensions */
2675 j = -1;
2676 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2677 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2678 --j;
2679 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002680 }
2681
Radek Krejci8d6b7422017-02-03 14:42:13 +01002682 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002683 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002684 }
2685 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002686 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002687 goto error;
2688 }
2689
Michal Vasko88c29542015-11-27 14:57:53 +01002690 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002691 }
2692
2693 if (c_must) {
2694 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002695 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002696 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002697 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2698 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002699 break;
Radek Krejci76512572015-08-04 09:47:08 +02002700 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002701 trg_must = &((struct lys_node_container *)dev_target)->must;
2702 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002703 break;
Radek Krejci76512572015-08-04 09:47:08 +02002704 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002705 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2706 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002707 break;
Radek Krejci76512572015-08-04 09:47:08 +02002708 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002709 trg_must = &((struct lys_node_list *)dev_target)->must;
2710 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002711 break;
Radek Krejci76512572015-08-04 09:47:08 +02002712 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002713 case LYS_ANYDATA:
2714 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2715 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002716 break;
2717 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002718 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2719 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002720 goto error;
2721 }
2722
Michal Vaskoc04173b2018-03-09 10:43:22 +01002723 dev_target->flags &= ~(LYS_XPCONF_DEP | LYS_XPSTATE_DEP);
Michal Vasko508a50d2016-09-07 14:50:33 +02002724
Radek Krejcieb00f512015-07-01 16:44:58 +02002725 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002726 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002727 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002728 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002729 } else if (d->mod == LY_DEVIATE_ADD) {
2730 /* reallocate the must array of the target */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002731 struct lys_restr *must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
2732 LY_CHECK_ERR_GOTO(!must, LOGMEM(ctx), error);
2733 *trg_must = must;
2734 d->must = calloc(c_must, sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02002735 d->must_size = c_must;
2736 } else { /* LY_DEVIATE_DEL */
2737 d->must = calloc(c_must, sizeof *d->must);
2738 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002739 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002740 }
2741 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002742 /* replace unique is forbidden */
2743 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002744 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002745 goto error;
2746 }
2747
Radek Krejcieb00f512015-07-01 16:44:58 +02002748 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002749 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002750 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2751 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002752 goto error;
2753 }
2754
Michal Vasko60f4b452016-02-12 11:02:55 +01002755 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002756 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002757 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002758 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002759 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002760 list->unique = d->unique;
2761 d->unique = &list->unique[list->unique_size];
2762 d->unique_size = c_uniq;
2763 } else { /* LY_DEVIATE_DEL */
2764 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002765 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002766 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002767 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002768 if (c_dflt) {
2769 if (d->mod == LY_DEVIATE_ADD) {
2770 /* check that there is no current value */
2771 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2772 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002773 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2774 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002775 goto error;
2776 }
2777
2778 /* check collision with mandatory/min-elements */
2779 if ((dev_target->flags & LYS_MAND_TRUE) ||
2780 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002781 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2782 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002783 "Adding the \"default\" statement is forbidden on %s statement.",
2784 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2785 goto error;
2786 }
2787 } else if (d->mod == LY_DEVIATE_RPL) {
2788 /* check that there was a value before */
2789 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2790 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002791 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2792 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002793 goto error;
2794 }
2795 }
2796
2797 if (dev_target->nodetype == LYS_LEAFLIST) {
2798 /* reallocate default list in the target */
2799 llist = (struct lys_node_leaflist *)dev_target;
2800 if (d->mod == LY_DEVIATE_ADD) {
2801 /* reallocate (enlarge) the unique array of the target */
2802 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002803 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002804 } else if (d->mod == LY_DEVIATE_RPL) {
2805 /* reallocate (replace) the unique array of the target */
2806 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002807 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002808 }
2809 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2810 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002811 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002812 }
2813 }
2814 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002815 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002816 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002817 if (c_ext) {
2818 /* some extensions may be already present from the substatements */
2819 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002820 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002821 d->ext = reallocated;
2822
2823 /* init memory */
2824 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2825 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002826
2827 /* process deviation properties with 0..n cardinality */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002828 deviate_must_index = 0;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002829 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2830 if (strcmp(child->ns->value, LY_NSYIN)) {
2831 /* extension */
2832 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2833 goto error;
2834 }
2835 d->ext_size++;
2836 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002837 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002838 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002839 goto error;
2840 }
2841
2842 /* find must to delete, we are ok with just matching conditions */
2843 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002844 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002845 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002846 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002847 /* ... and maintain the array */
2848 (*trg_must_size)--;
2849 if (i != *trg_must_size) {
2850 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2851 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2852 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2853 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2854 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2855 }
2856 if (!(*trg_must_size)) {
2857 free(*trg_must);
2858 *trg_must = NULL;
2859 } else {
2860 (*trg_must)[*trg_must_size].expr = NULL;
2861 (*trg_must)[*trg_must_size].dsc = NULL;
2862 (*trg_must)[*trg_must_size].ref = NULL;
2863 (*trg_must)[*trg_must_size].eapptag = NULL;
2864 (*trg_must)[*trg_must_size].emsg = NULL;
2865 }
2866
2867 i = -1; /* set match flag */
2868 break;
2869 }
2870 }
2871 d->must_size++;
2872 if (i != -1) {
2873 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002874 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002875 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002876 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002877 goto error;
2878 }
2879 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002880 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002881 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002882 goto error;
2883 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05002884 memcpy(d->must + deviate_must_index, &((*trg_must)[*trg_must_size]), sizeof *d->must);
2885 ++deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002886 (*trg_must_size)++;
2887 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002888
2889 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002890 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2891 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002892 goto error;
2893 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002894 } else if (!strcmp(child->name, "unique")) {
2895 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002896 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002897 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002898 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002899 goto error;
2900 }
2901
2902 /* find unique structures to delete */
2903 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002904 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002905 continue;
2906 }
2907
Radek Krejci581ce772015-11-10 17:22:40 +01002908 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002909 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002910 break;
2911 }
2912 }
2913
Radek Krejci581ce772015-11-10 17:22:40 +01002914 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002915 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002916 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002917 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002918 }
2919 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002920 /* ... and maintain the array */
2921 list->unique_size--;
2922 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002923 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2924 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002925 }
2926
2927 if (!list->unique_size) {
2928 free(list->unique);
2929 list->unique = NULL;
2930 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002931 list->unique[list->unique_size].expr_size = 0;
2932 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002933 }
2934
Radek Krejci6bd2c022017-02-01 15:04:49 +01002935 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002936 i = -1; /* set match flag */
2937 break;
2938 }
2939 }
2940
2941 d->unique_size++;
2942 if (i != -1) {
2943 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002944 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2945 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002946 goto error;
2947 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002948
2949 /* remove extensions of this unique instance from the target node */
2950 j = -1;
2951 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 +01002952 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002953 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2954 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002955 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002956 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002957 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002958 }
2959 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002960 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002961 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002962 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002963 list->unique_size++;
2964 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002965 goto error;
2966 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002967 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002968 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002969 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002970 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002971 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002972
2973 if (dev_target->nodetype == LYS_CHOICE) {
2974 choice = (struct lys_node_choice *)dev_target;
2975 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2976 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002977 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002978 goto error;
2979 }
2980 if (d->mod == LY_DEVIATE_DEL) {
2981 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002982 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2983 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002984 goto error;
2985 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002986 choice->dflt = NULL;
2987 /* remove extensions of this default instance from the target node */
2988 j = -1;
2989 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2990 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2991 --j;
2992 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002993 } else { /* add or replace */
2994 choice->dflt = node;
2995 if (!choice->dflt) {
2996 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002997 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002998 goto error;
2999 }
3000 }
3001 } else if (dev_target->nodetype == LYS_LEAF) {
3002 leaf = (struct lys_node_leaf *)dev_target;
3003 if (d->mod == LY_DEVIATE_DEL) {
3004 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003005 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3006 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003007 goto error;
3008 }
3009 /* remove value */
3010 lydict_remove(ctx, leaf->dflt);
3011 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01003012 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003013
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 (already checked) and replace */
3021 /* remove value */
3022 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01003023 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003024
3025 /* set new value */
3026 leaf->dflt = lydict_insert(ctx, value, u);
3027
Radek Krejcibd117f02016-11-04 16:28:08 +01003028 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02003029 ly_set_add(dflt_check, dev_target, 0);
3030 }
3031 } else { /* LYS_LEAFLIST */
3032 llist = (struct lys_node_leaflist *)dev_target;
3033 if (d->mod == LY_DEVIATE_DEL) {
3034 /* find and remove the value in target list */
3035 for (i = 0; i < llist->dflt_size; i++) {
3036 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
3037 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01003038 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003039 llist->dflt[i] = NULL;
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) {
Radek Krejcifebdad72017-02-06 11:35:51 +01003044 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003045 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3046 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003047 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003048 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003049 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003050 }
3051 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003052 break;
3053 }
3054 }
3055 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003056 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3057 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 +02003058 goto error;
3059 }
3060 } else {
3061 /* add or replace, anyway we place items into the deviate's list
3062 which propagates to the target */
3063 /* we just want to check that the value isn't already in the list */
3064 for (i = 0; i < llist->dflt_size; i++) {
3065 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003066 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3067 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003068 goto error;
3069 }
3070 }
3071 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003072 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003073
3074 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3075 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003076 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003077 }
3078 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003079 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003080 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003081
3082 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3083 /* consolidate the final list in the target after removing items from it */
3084 llist = (struct lys_node_leaflist *)dev_target;
3085 for (i = j = 0; j < llist->dflt_size; j++) {
3086 llist->dflt[i] = llist->dflt[j];
3087 if (llist->dflt[i]) {
3088 i++;
3089 }
3090 }
3091 llist->dflt_size = i + 1;
3092 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003093 }
3094
Michal Vasko43a1feb2016-03-07 12:03:02 +01003095 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003096 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003097 for (u = 0; u < dflt_check->number; ++u) {
3098 value = NULL;
3099 rc = EXIT_SUCCESS;
3100 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3101 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3102 value = leaf->dflt;
3103 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3104 } else { /* LYS_LEAFLIST */
3105 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3106 for (j = 0; j < llist->dflt_size; j++) {
3107 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3108 (struct lys_node *)(&llist->dflt[j]));
3109 if (rc == -1) {
3110 value = llist->dflt[j];
3111 break;
3112 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003113 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003114
Michal Vasko15a43372017-09-25 14:12:42 +02003115 }
3116 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003117 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3118 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003119 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3120 dev->target_name);
3121 goto error;
3122 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003123 }
3124 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003125
Radek Krejci27fe55e2016-09-13 17:13:35 +02003126 /* mark all the affected modules as deviated and implemented */
3127 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3128 mod = lys_node_module(parent);
3129 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003130 mod->deviated = 1; /* main module */
3131 parent->module->deviated = 1; /* possible submodule */
Michal Vasko0f437062018-06-08 15:52:39 +02003132 if (!mod->implemented) {
3133 mod->implemented = 1;
3134 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
3135 goto error;
3136 }
Radek Krejci2bb5be72017-02-27 13:07:25 +01003137 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003138 }
3139 }
3140
Radek Krejcid5a5c282016-08-15 15:38:08 +02003141 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003142 return EXIT_SUCCESS;
3143
3144error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003145 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003146 return EXIT_FAILURE;
3147}
3148
Michal Vasko0d343d12015-08-24 14:57:36 +02003149/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003150static int
Radek Krejcib8048692015-08-05 13:36:34 +02003151fill_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 +01003152 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003153{
Michal Vasko53b7da02018-02-13 15:28:42 +01003154 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003156 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003157 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003158 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003159 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003160
Michal Vasko591e0b22015-08-13 13:53:43 +02003161 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003162 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003163 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003164 if (!aug->target_name) {
3165 goto error;
3166 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003168
Radek Krejci07d0fb92017-01-13 14:11:05 +01003169 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003170 goto error;
3171 }
3172
Radek Krejcie534c132016-11-23 13:32:31 +01003173 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3174 if (strcmp(sub->ns->value, LY_NSYIN)) {
3175 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003176 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003177 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003178 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003179 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003180 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003181 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003182 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003183 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003184 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003185 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003186 goto error;
3187 }
3188
Radek Krejci5323b492017-01-16 15:40:11 +01003189 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003190 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003191 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003192 goto error;
3193 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003194 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003195 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003196
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003197 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003198 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003199 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003200 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003201 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003202 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003203 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003204 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003205 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003206 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003207 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003208 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003209 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003210 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003211 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003212 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003213 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003214 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003215 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003216 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003217 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003218 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003219 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003220 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003221 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003222 goto error;
3223 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003224
Radek Krejci1d82ef62015-08-07 14:44:40 +02003225 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003226 goto error;
3227 }
3228
Radek Krejci1d82ef62015-08-07 14:44:40 +02003229 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003230 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003231 }
3232
Radek Krejcie534c132016-11-23 13:32:31 +01003233 if (c_ftrs) {
3234 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003235 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003236 }
Radek Krejcie534c132016-11-23 13:32:31 +01003237 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003238 /* some extensions may be already present from the substatements */
3239 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003240 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003241 aug->ext = reallocated;
3242
3243 /* init memory */
3244 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003245 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003246
Radek Krejcie534c132016-11-23 13:32:31 +01003247 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3248 if (strcmp(sub->ns->value, LY_NSYIN)) {
3249 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003250 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 +01003251 aug->ext_size++;
3252 if (ret) {
3253 goto error;
3254 }
3255 } else if (!strcmp(sub->name, "if-feature")) {
3256 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003257 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003258 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003259 goto error;
3260 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003261 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003262 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003263 }
3264
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003265 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003266 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003267 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003268 * when the uses does and cannot be resolved now for sure
3269 * (the grouping was not yet copied into uses).
3270 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003271 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003272 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003273 goto error;
3274 }
Michal Vasko49291b32015-08-06 09:49:41 +02003275 }
Radek Krejci106efc02015-06-10 14:36:27 +02003276
Michal Vasko508a50d2016-09-07 14:50:33 +02003277 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003278 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003279 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003280 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003281 goto error;
3282 }
3283 } else {
3284 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3285 goto error;
3286 }
3287 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003288 }
3289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003291
3292error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003294}
3295
Michal Vasko0d343d12015-08-24 14:57:36 +02003296/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003298fill_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 +02003299{
Michal Vasko53b7da02018-02-13 15:28:42 +01003300 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003301 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 struct lyxml_elem *sub, *next;
3303 const char *value;
3304 char *endptr;
3305 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003306 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 int r;
3308 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003309 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003310
Radek Krejci363bd4a2016-07-29 14:30:20 +02003311 assert(uses);
3312 module = uses->module; /* shorthand */
3313
Michal Vasko53b7da02018-02-13 15:28:42 +01003314 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003315 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003316 if (!rfn->target_name) {
3317 goto error;
3318 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003321 if (!sub->ns) {
3322 /* garbage */
3323 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003324 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003325 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003326 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003327 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003328
Radek Krejci411b1bf2017-01-23 16:40:05 +01003329 } else if (!strcmp(sub->name, "description")) {
3330 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003331 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003332 goto error;
3333 }
3334
Radek Krejci8d6b7422017-02-03 14:42:13 +01003335 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003336 goto error;
3337 }
3338
Michal Vasko53b7da02018-02-13 15:28:42 +01003339 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003340 if (!rfn->dsc) {
3341 goto error;
3342 }
3343 } else if (!strcmp(sub->name, "reference")) {
3344 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003345 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003346 goto error;
3347 }
3348
Radek Krejci8d6b7422017-02-03 14:42:13 +01003349 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003350 goto error;
3351 }
3352
Michal Vasko53b7da02018-02-13 15:28:42 +01003353 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003354 if (!rfn->ref) {
3355 goto error;
3356 }
3357 } else if (!strcmp(sub->name, "config")) {
3358 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003359 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003360 goto error;
3361 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003362 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003363 if (!strcmp(value, "false")) {
3364 rfn->flags |= LYS_CONFIG_R;
3365 } else if (!strcmp(value, "true")) {
3366 rfn->flags |= LYS_CONFIG_W;
3367 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003368 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003369 goto error;
3370 }
3371 rfn->flags |= LYS_CONFIG_SET;
3372
Radek Krejci8d6b7422017-02-03 14:42:13 +01003373 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003374 goto error;
3375 }
Radek Krejcie534c132016-11-23 13:32:31 +01003376 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003377 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 /* check possibility of statements combination */
3380 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003381 if (c_dflt) {
3382 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003383 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003384 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003385 goto error;
3386 }
Radek Krejci200bf712016-08-16 17:11:04 +02003387 rfn->target_type &= LYS_LEAFLIST;
3388 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003389 if (module->version < 2) {
3390 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3391 } else {
3392 /* YANG 1.1 */
3393 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3394 }
Radek Krejci200bf712016-08-16 17:11:04 +02003395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003397 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3398 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 goto error;
3400 }
3401 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003402 if (module->version < 2) {
3403 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3404 } else {
3405 /* YANG 1.1 */
3406 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003409
Michal Vasko53b7da02018-02-13 15:28:42 +01003410 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003411 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 +01003412 goto error;
3413 }
Radek Krejci200bf712016-08-16 17:11:04 +02003414 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003415 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 } else if (!strcmp(sub->name, "mandatory")) {
3417 /* leaf, choice or anyxml */
3418 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003419 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 goto error;
3421 }
3422 /* just checking the flags in leaf is not sufficient, we would allow
3423 * multiple mandatory statements with the "false" value
3424 */
3425 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 /* check possibility of statements combination */
3428 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003429 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003431 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3432 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 goto error;
3434 }
3435 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003436 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003438
Michal Vasko53b7da02018-02-13 15:28:42 +01003439 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003441 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003443 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003445 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 goto error;
3447 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003448 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003449 goto error;
3450 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 } else if (!strcmp(sub->name, "min-elements")) {
3452 /* list or leaf-list */
3453 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003454 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 goto error;
3456 }
3457 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 /* check possibility of statements combination */
3460 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003461 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003463 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3464 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 goto error;
3466 }
3467 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003468 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003470
Michal Vasko53b7da02018-02-13 15:28:42 +01003471 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 while (isspace(value[0])) {
3473 value++;
3474 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 /* convert it to uint32_t */
3477 errno = 0;
3478 endptr = NULL;
3479 val = strtoul(value, &endptr, 10);
3480 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003481 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 goto error;
3483 }
3484 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003485 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003486
Radek Krejci8d6b7422017-02-03 14:42:13 +01003487 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003488 goto error;
3489 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 } else if (!strcmp(sub->name, "max-elements")) {
3491 /* list or leaf-list */
3492 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003493 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 goto error;
3495 }
3496 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 /* check possibility of statements combination */
3499 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003500 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003502 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3503 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 goto error;
3505 }
3506 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003507 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003509
Michal Vasko53b7da02018-02-13 15:28:42 +01003510 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 while (isspace(value[0])) {
3512 value++;
3513 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003514
Radek Krejci0d7b2472016-02-12 11:11:03 +01003515 if (!strcmp(value, "unbounded")) {
3516 rfn->mod.list.max = 0;
3517 } else {
3518 /* convert it to uint32_t */
3519 errno = 0;
3520 endptr = NULL;
3521 val = strtoul(value, &endptr, 10);
3522 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003523 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003524 goto error;
3525 }
3526 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003527 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003528 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003529
Radek Krejci8d6b7422017-02-03 14:42:13 +01003530 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003531 goto error;
3532 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 } else if (!strcmp(sub->name, "presence")) {
3534 /* container */
3535 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003536 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 goto error;
3538 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 /* check possibility of statements combination */
3541 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003542 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003544 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3545 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 goto error;
3547 }
3548 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003549 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003551
Michal Vasko53b7da02018-02-13 15:28:42 +01003552 GETVAL(ctx, value, sub, "value");
3553 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003554
Radek Krejci8d6b7422017-02-03 14:42:13 +01003555 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003556 goto error;
3557 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003559 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 /* check possibility of statements combination */
3561 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003562 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003563 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003564 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3565 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 goto error;
3567 }
3568 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003569 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003571
Michal Vasko53b7da02018-02-13 15:28:42 +01003572 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003574 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003575
Radek Krejci363bd4a2016-07-29 14:30:20 +02003576 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3577 /* leaf, leaf-list, list, container or anyxml */
3578 /* check possibility of statements combination */
3579 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003580 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003581 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003582 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3583 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003584 goto error;
3585 }
3586 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003587 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003588 }
3589
Michal Vasko53b7da02018-02-13 15:28:42 +01003590 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003591 c_ftrs++;
3592 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003594 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 goto error;
3596 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003597
Michal Vasko53b7da02018-02-13 15:28:42 +01003598 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 /* process nodes with cardinality of 0..n */
3602 if (c_must) {
3603 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003604 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003606 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003607 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003608 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 }
Radek Krejci200bf712016-08-16 17:11:04 +02003610 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003611 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003612 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003613 }
Radek Krejcie534c132016-11-23 13:32:31 +01003614 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003615 /* some extensions may be already present from the substatements */
3616 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003617 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003618 rfn->ext = reallocated;
3619
3620 /* init memory */
3621 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003622 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003623
Radek Krejcie534c132016-11-23 13:32:31 +01003624 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3625 if (strcmp(sub->ns->value, LY_NSYIN)) {
3626 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003627 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 +01003628 rfn->ext_size++;
3629 if (r) {
3630 goto error;
3631 }
3632 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003633 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003634 rfn->iffeature_size++;
3635 if (r) {
3636 goto error;
3637 }
Radek Krejci200bf712016-08-16 17:11:04 +02003638 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003639 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003640 rfn->must_size++;
3641 if (r) {
3642 goto error;
3643 }
Radek Krejci200bf712016-08-16 17:11:04 +02003644 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003645 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003646
3647 /* check for duplicity */
3648 for (r = 0; r < rfn->dflt_size; r++) {
3649 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003650 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3651 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003652 goto error;
3653 }
3654 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003655 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003656 }
3657 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003660
3661error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003662 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003663}
3664
Michal Vasko0d343d12015-08-24 14:57:36 +02003665/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666static int
Radek Krejcie534c132016-11-23 13:32:31 +01003667fill_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 +02003668{
Michal Vasko53b7da02018-02-13 15:28:42 +01003669 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003670 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003672 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003673 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003674
Radek Krejcie534c132016-11-23 13:32:31 +01003675 /* init */
3676 memset(&exts, 0, sizeof exts);
3677
3678 LY_TREE_FOR_SAFE(yin->child, next, child) {
3679 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003680 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003681 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003682 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3683 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003684 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003685 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003686 lyxml_unlink_elem(ctx, child, 2);
3687 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003688 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003689 GETVAL(ctx, value, child, "value");
3690 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 goto error;
3692 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003693 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003694
Radek Krejci8d6b7422017-02-03 14:42:13 +01003695 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003696 goto error;
3697 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 } else if (!strcmp(child->name, "revision-date")) {
3699 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003700 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003701 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003703 GETVAL(ctx, value, child, "date");
3704 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 goto error;
3706 }
3707 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003708
Radek Krejci8d6b7422017-02-03 14:42:13 +01003709 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003710 goto error;
3711 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003712 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003713 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003714 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003715 goto error;
3716 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003717 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003718 goto error;
3719 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003720 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003721 if (!imp->dsc) {
3722 goto error;
3723 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003724 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003725 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003726 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003727 goto error;
3728 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003729 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003730 goto error;
3731 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003732 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003733 if (!imp->ref) {
3734 goto error;
3735 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003737 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 goto error;
3739 }
3740 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 /* check mandatory information */
3743 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003744 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 goto error;
3746 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003747
Radek Krejcie534c132016-11-23 13:32:31 +01003748 /* process extensions */
3749 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003750 /* some extensions may be already present from the substatements */
3751 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003752 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003753 imp->ext = reallocated;
3754
3755 /* init memory */
3756 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3757
Radek Krejcie534c132016-11-23 13:32:31 +01003758 LY_TREE_FOR_SAFE(exts.child, next, child) {
3759 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003760 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 +01003761 imp->ext_size++;
3762 if (r) {
3763 goto error;
3764 }
3765 }
3766 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003767
Michal Vasko53b7da02018-02-13 15:28:42 +01003768 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003769 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003770
3771error:
Radek Krejcie534c132016-11-23 13:32:31 +01003772 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003773 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003774 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003775 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003776}
3777
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003778/* logs directly
3779 * returns:
3780 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003781 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003782 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003784fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3785 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003786{
Michal Vasko53b7da02018-02-13 15:28:42 +01003787 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003788 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003790 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003791 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003792
Radek Krejcie534c132016-11-23 13:32:31 +01003793 /* init */
3794 memset(&exts, 0, sizeof exts);
3795
3796 LY_TREE_FOR_SAFE(yin->child, next, child) {
3797 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003798 /* garbage */
3799 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003800 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3801 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003802 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003803 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003804 lyxml_unlink_elem(ctx, child, 2);
3805 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003806 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003808 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 goto error;
3810 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003811 GETVAL(ctx, value, child, "date");
3812 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 goto error;
3814 }
3815 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003816
Radek Krejci8d6b7422017-02-03 14:42:13 +01003817 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003818 goto error;
3819 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003820 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003821 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003822 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003823 goto error;
3824 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003825 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003826 goto error;
3827 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003828 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003829 if (!inc->dsc) {
3830 goto error;
3831 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003832 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003833 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003834 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003835 goto error;
3836 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003837 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003838 goto error;
3839 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003840 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003841 if (!inc->ref) {
3842 goto error;
3843 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003845 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 goto error;
3847 }
3848 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003849
Radek Krejcie534c132016-11-23 13:32:31 +01003850 /* process extensions */
3851 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003852 /* some extensions may be already present from the substatements */
3853 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003854 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003855 inc->ext = reallocated;
3856
3857 /* init memory */
3858 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3859
Radek Krejcie534c132016-11-23 13:32:31 +01003860 LY_TREE_FOR_SAFE(exts.child, next, child) {
3861 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003862 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 +01003863 inc->ext_size++;
3864 if (r) {
3865 goto error;
3866 }
3867 }
3868 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003869
Michal Vasko53b7da02018-02-13 15:28:42 +01003870 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003871 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003872
3873error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003874 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003875}
3876
Michal Vasko0d343d12015-08-24 14:57:36 +02003877/* logs directly
3878 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003879 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003880 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003881 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003882 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003883static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003884read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3885 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003886{
Radek Krejcie4dce292017-10-30 11:16:47 +01003887 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 const char *value;
3889 struct lyxml_elem *sub, *next;
3890 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003891 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003894 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003895 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003898 GETVAL(ctx, value, xmlnode, "name");
3899 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 goto error;
3901 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003902 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003903 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 /* process local parameters */
3906 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003907 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003908 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003909 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003910 continue;
3911 }
3912 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003913 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003914 continue;
3915 }
3916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003918 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003919 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003920 goto error;
3921 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003922
Radek Krejci8d6b7422017-02-03 14:42:13 +01003923 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003924 goto error;
3925 }
3926
Radek Krejci1d82ef62015-08-07 14:44:40 +02003927 node->dsc = read_yin_subnode(ctx, sub, "text");
3928 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003929 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 }
3931 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003932 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003933 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 goto error;
3935 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003936
Radek Krejci8d6b7422017-02-03 14:42:13 +01003937 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003938 goto error;
3939 }
3940
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 node->ref = read_yin_subnode(ctx, sub, "text");
3942 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003943 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 }
3945 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003946 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003947 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 goto error;
3949 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003950 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003958 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003959 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003961
Radek Krejci8d6b7422017-02-03 14:42:13 +01003962 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003963 goto error;
3964 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003965 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3966 if (opt & OPT_CFG_PARSE) {
3967 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003968 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003969 goto error;
3970 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003971 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003972 if (!strcmp(value, "false")) {
3973 node->flags |= LYS_CONFIG_R;
3974 } else if (!strcmp(value, "true")) {
3975 node->flags |= LYS_CONFIG_W;
3976 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003977 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003978 goto error;
3979 }
3980 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003981
Radek Krejci8d6b7422017-02-03 14:42:13 +01003982 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003983 goto error;
3984 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003987 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003988 continue;
3989 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003990 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003991 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003992
Michal Vaskoe022a562016-09-27 14:24:15 +02003993 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003994 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003995 if (parent) {
3996 node->flags |= parent->flags & LYS_CONFIG_MASK;
3997 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003999 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 }
4001 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004002
Radek Krejci2cc25322017-09-06 16:32:02 +02004003 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
4004 /* status is not inherited by specification, but it not make sense to have
4005 * current in deprecated or deprecated in obsolete, so we print warning
4006 * and fix the schema by inheriting */
4007 if (!(node->flags & (LYS_STATUS_MASK))) {
4008 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01004009 if (stmt_type == LYEXT_PAR_NODE) {
4010 p = node->parent;
4011 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01004012 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004013 node->parent = p;
4014 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01004015 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01004016 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004017 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
4018 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02004019 free(str);
4020 node->flags |= parent->flags & LYS_STATUS_MASK;
4021 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
4022 /* invalid combination of statuses */
4023 switch (node->flags & LYS_STATUS_MASK) {
4024 case 0:
4025 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01004026 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004027 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
4028 break;
4029 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01004030 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02004031 "obsolete", parent->name);
4032 break;
4033 }
4034 goto error;
4035 }
4036 }
4037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004038 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004039
4040error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004042}
4043
Michal Vasko0d343d12015-08-24 14:57:36 +02004044/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004045static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004046read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004047{
Michal Vasko53b7da02018-02-13 15:28:42 +01004048 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004049 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004050 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004051 const char *value;
4052
4053 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004054 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004055
Michal Vasko53b7da02018-02-13 15:28:42 +01004056 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004057 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004058 if (!retval->cond) {
4059 goto error;
4060 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004061
Radek Krejci5323b492017-01-16 15:40:11 +01004062 LY_TREE_FOR_SAFE(yin->child, next, child) {
4063 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004064 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004065 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004066 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4067 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004068 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004069 goto error;
4070 }
4071 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004072 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004073 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004074 goto error;
4075 }
Radek Krejci5323b492017-01-16 15:40:11 +01004076
Radek Krejci8d6b7422017-02-03 14:42:13 +01004077 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004078 goto error;
4079 }
4080
Michal Vasko53b7da02018-02-13 15:28:42 +01004081 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004082 if (!retval->dsc) {
4083 goto error;
4084 }
4085 } else if (!strcmp(child->name, "reference")) {
4086 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004087 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004088 goto error;
4089 }
Radek Krejci5323b492017-01-16 15:40:11 +01004090
Radek Krejci8d6b7422017-02-03 14:42:13 +01004091 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004092 goto error;
4093 }
4094
Michal Vasko53b7da02018-02-13 15:28:42 +01004095 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004096 if (!retval->ref) {
4097 goto error;
4098 }
4099 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004100 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004101 goto error;
4102 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004103 }
4104
4105 return retval;
4106
4107error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004108 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004109 return NULL;
4110}
4111
Michal Vasko0d343d12015-08-24 14:57:36 +02004112/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004113static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004114read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004115 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004116{
Michal Vasko53b7da02018-02-13 15:28:42 +01004117 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004118 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004119 struct lys_node_case *cs;
4120 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004121 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004122 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004123
Radek Krejcie867c852015-08-27 09:52:34 +02004124 /* init */
4125 memset(&root, 0, sizeof root);
4126
Radek Krejci1d82ef62015-08-07 14:44:40 +02004127 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004128 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004129 cs->nodetype = LYS_CASE;
4130 cs->prev = (struct lys_node *)cs;
4131 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004132
Radek Krejci07d0fb92017-01-13 14:11:05 +01004133 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004134 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 goto error;
4136 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004137
Michal Vasko3e3228d2017-02-24 14:55:32 +01004138 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004139
Michal Vasko3a0043f2015-08-12 12:11:30 +02004140 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004141 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004142 goto error;
4143 }
4144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 /* process choice's specific children */
4146 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004147 if (strcmp(sub->ns->value, LY_NSYIN)) {
4148 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004149 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004150 c_ext++;
4151 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004152 !strcmp(sub->name, "leaf-list") ||
4153 !strcmp(sub->name, "leaf") ||
4154 !strcmp(sub->name, "list") ||
4155 !strcmp(sub->name, "uses") ||
4156 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004157 !strcmp(sub->name, "anyxml") ||
4158 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004159
Michal Vasko53b7da02018-02-13 15:28:42 +01004160 lyxml_unlink_elem(ctx, sub, 2);
4161 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004162 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004163 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004164 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004165 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004166 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004167 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004168 goto error;
4169 }
4170
Radek Krejci5323b492017-01-16 15:40:11 +01004171 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004172 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004173 goto error;
4174 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004175
Michal Vasko53b7da02018-02-13 15:28:42 +01004176 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004178 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004179 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004181 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004182
Radek Krejci3cf9e222015-06-18 11:37:50 +02004183 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004184 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004185 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004186 }
Radek Krejcie534c132016-11-23 13:32:31 +01004187 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004188 /* some extensions may be already present from the substatements */
4189 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004190 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004191 retval->ext = reallocated;
4192
4193 /* init memory */
4194 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004195 }
Radek Krejci21c81652017-01-23 10:42:55 +01004196
Radek Krejcie534c132016-11-23 13:32:31 +01004197 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4198 if (strcmp(sub->ns->value, LY_NSYIN)) {
4199 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004200 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 +01004201 retval->ext_size++;
4202 if (ret) {
4203 goto error;
4204 }
4205 } else {
4206 /* if-feature */
4207 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4208 cs->iffeature_size++;
4209 if (ret) {
4210 goto error;
4211 }
4212 }
4213 }
Radek Krejcib388c152015-06-04 17:03:03 +02004214
Michal Vasko29fc0182015-08-24 15:02:39 +02004215 /* last part - process data nodes */
4216 LY_TREE_FOR_SAFE(root.child, next, sub) {
4217 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004218 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004219 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004220 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004221 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004222 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004223 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004224 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004225 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004226 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004227 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004228 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004229 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004230 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004231 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004232 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004233 }
4234 if (!node) {
4235 goto error;
4236 }
4237
Michal Vasko53b7da02018-02-13 15:28:42 +01004238 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004239 }
4240
Michal Vasko508a50d2016-09-07 14:50:33 +02004241 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004242 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004243 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004244 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004245 goto error;
4246 }
4247 } else {
4248 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4249 goto error;
4250 }
4251 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004252 }
4253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004255
4256error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004257 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004258 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004259 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004260 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004262 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004263}
4264
Michal Vasko0d343d12015-08-24 14:57:36 +02004265/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004266static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004267read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004268 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004269{
Radek Krejci629cdef2016-06-06 15:06:36 +02004270 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004272 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004273 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004274 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004275 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004276 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004279 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004280
Radek Krejci76512572015-08-04 09:47:08 +02004281 choice->nodetype = LYS_CHOICE;
4282 choice->prev = (struct lys_node *)choice;
4283 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004284
Radek Krejci07d0fb92017-01-13 14:11:05 +01004285 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004286 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4287 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4288 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 goto error;
4290 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004291
Michal Vasko3e3228d2017-02-24 14:55:32 +01004292 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004293
Michal Vasko3a0043f2015-08-12 12:11:30 +02004294 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004295 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004296 goto error;
4297 }
4298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 /* process choice's specific children */
4300 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004301 if (strcmp(sub->ns->value, LY_NSYIN)) {
4302 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004303 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004304 c_ext++;
4305 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004306 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004307 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004308 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004309 goto error;
4310 }
4311 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004312 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 goto error;
4314 }
4315 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004316 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 goto error;
4318 }
4319 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004320 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 goto error;
4322 }
4323 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004324 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 goto error;
4326 }
4327 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004328 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004329 goto error;
4330 }
4331 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004332 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004333 goto error;
4334 }
4335 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004336 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004337 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004338 goto error;
4339 }
Radek Krejci21c81652017-01-23 10:42:55 +01004340
Radek Krejci8d6b7422017-02-03 14:42:13 +01004341 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004342 goto error;
4343 }
4344
Radek Krejci629cdef2016-06-06 15:06:36 +02004345 dflt = sub;
4346 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004347 continue;
4348 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350 } else if (!strcmp(sub->name, "mandatory")) {
4351 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004352 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004353 goto error;
4354 }
4355 /* just checking the flags in leaf is not sufficient, we would allow
4356 * multiple mandatory statements with the "false" value
4357 */
4358 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004359
Michal Vasko53b7da02018-02-13 15:28:42 +01004360 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004361 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004362 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004363 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004364 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004365 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004366 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 goto error;
4368 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004369
Radek Krejci8d6b7422017-02-03 14:42:13 +01004370 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004371 goto error;
4372 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004373 } else if (!strcmp(sub->name, "when")) {
4374 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004375 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004376 goto error;
4377 }
4378
Radek Krejci5323b492017-01-16 15:40:11 +01004379 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004380 if (!choice->when) {
4381 goto error;
4382 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004383 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004384 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004385 c_ftrs++;
4386
Michal Vasko345da0a2015-12-02 10:35:55 +01004387 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004388 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004389 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004390 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004391 goto error;
4392 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004393 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004394 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004397
Radek Krejci1d82ef62015-08-07 14:44:40 +02004398 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004399 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004401
Radek Krejci3cf9e222015-06-18 11:37:50 +02004402 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004403 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004404 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004405 }
Radek Krejcie534c132016-11-23 13:32:31 +01004406 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004407 /* some extensions may be already present from the substatements */
4408 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004409 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004410 retval->ext = reallocated;
4411
4412 /* init memory */
4413 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004414 }
4415
Radek Krejcie534c132016-11-23 13:32:31 +01004416 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4417 if (strcmp(sub->ns->value, LY_NSYIN)) {
4418 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004419 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 +01004420 retval->ext_size++;
4421 if (ret) {
4422 goto error;
4423 }
4424 } else {
4425 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4426 choice->iffeature_size++;
4427 if (ret) {
4428 goto error;
4429 }
4430 }
4431 }
4432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004434 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004435 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4436 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004437 goto error;
4438 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004441 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004442 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004443 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004444 goto error;
4445 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004446 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004448
Michal Vasko508a50d2016-09-07 14:50:33 +02004449 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004450 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004451 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004452 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004453 goto error;
4454 }
4455 } else {
4456 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4457 goto error;
4458 }
4459 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004460 }
4461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004462 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004463
4464error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004465 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004466 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004468}
4469
Michal Vasko0d343d12015-08-24 14:57:36 +02004470/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004471static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004472read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004473 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004474{
Michal Vasko53b7da02018-02-13 15:28:42 +01004475 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004476 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004477 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004478 struct lyxml_elem *sub, *next;
4479 const char *value;
4480 int r;
4481 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004482 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004483 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004486 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004487
Radek Krejcibf2abff2016-08-23 15:51:52 +02004488 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004489 anyxml->prev = (struct lys_node *)anyxml;
4490 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004491
Radek Krejci07d0fb92017-01-13 14:11:05 +01004492 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004493 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004494 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 goto error;
4496 }
Radek Krejci863c2852015-06-03 15:47:11 +02004497
Michal Vasko3e3228d2017-02-24 14:55:32 +01004498 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004499
Radek Krejcic189a952016-07-11 15:27:07 +02004500 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004501 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004502 goto error;
4503 }
4504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004505 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004506 if (strcmp(sub->ns->value, LY_NSYIN)) {
4507 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004508 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004509 c_ext++;
4510 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004512 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 goto error;
4514 }
4515 /* just checking the flags in leaf is not sufficient, we would allow
4516 * multiple mandatory statements with the "false" value
4517 */
4518 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004519
Michal Vasko53b7da02018-02-13 15:28:42 +01004520 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004522 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004523 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004524 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004525 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004526 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 goto error;
4528 }
4529 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004530
Radek Krejci8d6b7422017-02-03 14:42:13 +01004531 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004532 goto error;
4533 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004534 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004535 } else if (!strcmp(sub->name, "when")) {
4536 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004537 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004538 goto error;
4539 }
4540
Radek Krejci5323b492017-01-16 15:40:11 +01004541 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004542 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004543 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004544 goto error;
4545 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004546 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004547 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004548 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004550 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004551 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004552 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004555 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004557 }
4558 }
Radek Krejci863c2852015-06-03 15:47:11 +02004559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 /* middle part - process nodes with cardinality of 0..n */
4561 if (c_must) {
4562 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004563 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004565 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004566 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004567 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004568 }
Radek Krejcie534c132016-11-23 13:32:31 +01004569 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004570 /* some extensions may be already present from the substatements */
4571 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004572 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004573 retval->ext = reallocated;
4574
4575 /* init memory */
4576 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004577 }
Radek Krejci863c2852015-06-03 15:47:11 +02004578
Radek Krejcie534c132016-11-23 13:32:31 +01004579 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4580 if (strcmp(sub->ns->value, LY_NSYIN)) {
4581 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004582 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 +01004583 retval->ext_size++;
4584 if (r) {
4585 goto error;
4586 }
4587 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004588 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004589 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590 if (r) {
4591 goto error;
4592 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004593 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004594 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004595 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004596 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004597 goto error;
4598 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 }
Radek Krejci863c2852015-06-03 15:47:11 +02004601
Michal Vasko508a50d2016-09-07 14:50:33 +02004602 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004603 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004604 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004605 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004606 goto error;
4607 }
4608 } else {
4609 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4610 goto error;
4611 }
4612 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004613 }
4614
PavolVican92f23622017-12-12 13:35:56 +01004615 for (r = 0; r < retval->ext_size; ++r) {
4616 /* set flag, which represent LYEXT_OPT_VALID */
4617 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004618 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004619 break;
4620 }
4621 }
4622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004624
4625error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004626 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004627 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004628}
4629
Michal Vasko0d343d12015-08-24 14:57:36 +02004630/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004631static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004632read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004633 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004634{
Michal Vasko53b7da02018-02-13 15:28:42 +01004635 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004636 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004637 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 struct lyxml_elem *sub, *next;
4639 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004640 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004641 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004642 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004645 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004646
Radek Krejci76512572015-08-04 09:47:08 +02004647 leaf->nodetype = LYS_LEAF;
4648 leaf->prev = (struct lys_node *)leaf;
4649 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004650
Radek Krejci07d0fb92017-01-13 14:11:05 +01004651 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004652 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4653 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4654 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 goto error;
4656 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004657
Michal Vasko3e3228d2017-02-24 14:55:32 +01004658 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004659
Radek Krejcic189a952016-07-11 15:27:07 +02004660 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004661 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004662 goto error;
4663 }
4664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004666 if (strcmp(sub->ns->value, LY_NSYIN)) {
4667 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004668 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004669 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004670 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004671 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004672 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004673 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 goto error;
4675 }
Michal Vasko88c29542015-11-27 14:57:53 +01004676 /* HACK for unres */
4677 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004678 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004679 /* postpone type resolution when if-feature parsing is done since we need
4680 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004681 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 } else if (!strcmp(sub->name, "default")) {
4683 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004684 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 goto error;
4686 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004687 GETVAL(ctx, value, sub, "value");
4688 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004689
Radek Krejci8d6b7422017-02-03 14:42:13 +01004690 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004691 goto error;
4692 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004693 } else if (!strcmp(sub->name, "units")) {
4694 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004695 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004696 goto error;
4697 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004698 GETVAL(ctx, value, sub, "name");
4699 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004700
Radek Krejci8d6b7422017-02-03 14:42:13 +01004701 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004702 goto error;
4703 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 } else if (!strcmp(sub->name, "mandatory")) {
4705 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004706 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 goto error;
4708 }
4709 /* just checking the flags in leaf is not sufficient, we would allow
4710 * multiple mandatory statements with the "false" value
4711 */
4712 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004713
Michal Vasko53b7da02018-02-13 15:28:42 +01004714 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004715 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004716 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004717 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004718 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004719 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004720 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 goto error;
4722 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004723
Radek Krejci8d6b7422017-02-03 14:42:13 +01004724 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004725 goto error;
4726 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004727 } else if (!strcmp(sub->name, "when")) {
4728 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004729 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004730 goto error;
4731 }
4732
Radek Krejci5323b492017-01-16 15:40:11 +01004733 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004734 if (!leaf->when) {
4735 goto error;
4736 }
4737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004739 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004740 c_must++;
4741 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004742 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004743 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004744 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004748 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004751
Michal Vasko88c29542015-11-27 14:57:53 +01004752 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004755 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004756 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004757 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 goto error;
4759 }
Michal Vasko478c4652016-07-21 12:55:01 +02004760 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004761 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4762 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004763 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4764 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 /* middle part - process nodes with cardinality of 0..n */
4768 if (c_must) {
4769 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004770 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004772 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004773 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004774 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004775 }
Radek Krejcie534c132016-11-23 13:32:31 +01004776 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004777 /* some extensions may be already present from the substatements */
4778 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004779 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004780 retval->ext = reallocated;
4781
4782 /* init memory */
4783 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004784 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004785
Radek Krejcie534c132016-11-23 13:32:31 +01004786 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4787 if (strcmp(sub->ns->value, LY_NSYIN)) {
4788 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004789 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 +01004790 retval->ext_size++;
4791 if (r) {
4792 goto error;
4793 }
4794 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004795 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004796 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 if (r) {
4798 goto error;
4799 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004800 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004801 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004802 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004803 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004804 goto error;
4805 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004807 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004808
Radek Krejcicbb473e2016-09-16 14:48:32 +02004809 /* finalize type parsing */
4810 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4811 leaf->type.der = NULL;
4812 goto error;
4813 }
4814
4815 /* check default value (if not defined, there still could be some restrictions
4816 * that need to be checked against a default value from a derived type) */
Michal Vasko6a057782018-03-09 13:24:33 +01004817 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004818 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4819 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004820 goto error;
4821 }
4822
Michal Vasko508a50d2016-09-07 14:50:33 +02004823 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004824 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004825 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004826 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004827 goto error;
4828 }
4829 } else {
4830 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4831 goto error;
4832 }
4833 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004834 }
4835
PavolVican92f23622017-12-12 13:35:56 +01004836 for (r = 0; r < retval->ext_size; ++r) {
4837 /* set flag, which represent LYEXT_OPT_VALID */
4838 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004839 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004840 break;
4841 }
4842 }
4843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004845
4846error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004847 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004848 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004849}
4850
Michal Vasko0d343d12015-08-24 14:57:36 +02004851/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004852static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004853read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004854 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004855{
Michal Vasko53b7da02018-02-13 15:28:42 +01004856 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004857 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004858 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 struct lyxml_elem *sub, *next;
4860 const char *value;
4861 char *endptr;
4862 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004863 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004864 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004866 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004869 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004870
Radek Krejci76512572015-08-04 09:47:08 +02004871 llist->nodetype = LYS_LEAFLIST;
4872 llist->prev = (struct lys_node *)llist;
4873 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004874
Radek Krejci07d0fb92017-01-13 14:11:05 +01004875 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004876 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4877 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4878 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 goto error;
4880 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004881
Michal Vasko3e3228d2017-02-24 14:55:32 +01004882 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004883
Radek Krejcic189a952016-07-11 15:27:07 +02004884 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004885 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004886 goto error;
4887 }
4888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004890 if (strcmp(sub->ns->value, LY_NSYIN)) {
4891 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004892 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004893 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004894 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004895 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004896 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004897 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 goto error;
4899 }
Michal Vasko88c29542015-11-27 14:57:53 +01004900 /* HACK for unres */
4901 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004902 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004903 /* postpone type resolution when if-feature parsing is done since we need
4904 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004905 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 } else if (!strcmp(sub->name, "units")) {
4907 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004908 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 goto error;
4910 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004911 GETVAL(ctx, value, sub, "name");
4912 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004913
Radek Krejci8d6b7422017-02-03 14:42:13 +01004914 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004915 goto error;
4916 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 } else if (!strcmp(sub->name, "ordered-by")) {
4918 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004919 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 goto error;
4921 }
4922 /* just checking the flags in llist is not sufficient, we would
4923 * allow multiple ordered-by statements with the "system" value
4924 */
4925 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004926
Radek Krejci1574a8d2015-08-03 14:16:52 +02004927 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4929 * state data
4930 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004931 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004932 continue;
4933 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004934
Michal Vasko53b7da02018-02-13 15:28:42 +01004935 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004937 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004938 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004939 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004940 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004941 } /* else system is the default value, so we can ignore it */
4942
Radek Krejci8d6b7422017-02-03 14:42:13 +01004943 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004944 goto error;
4945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004947 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004948 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004949 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004950 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004951 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004952 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004954 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004955 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004956 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 +01004957 goto error;
4958 }
4959
Michal Vasko53b7da02018-02-13 15:28:42 +01004960 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004961 c_dflt++;
4962 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 } else if (!strcmp(sub->name, "min-elements")) {
4965 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004966 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 goto error;
4968 }
4969 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004970
Michal Vasko53b7da02018-02-13 15:28:42 +01004971 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004972 while (isspace(value[0])) {
4973 value++;
4974 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 /* convert it to uint32_t */
4977 errno = 0;
4978 endptr = NULL;
4979 val = strtoul(value, &endptr, 10);
4980 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004981 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 goto error;
4983 }
4984 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004985 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004986 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4987 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004988 goto error;
4989 }
Radek Krejci5323b492017-01-16 15:40:11 +01004990
Radek Krejci8d6b7422017-02-03 14:42:13 +01004991 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004992 goto error;
4993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004994 } else if (!strcmp(sub->name, "max-elements")) {
4995 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004996 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 goto error;
4998 }
4999 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005000
Michal Vasko53b7da02018-02-13 15:28:42 +01005001 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005002 while (isspace(value[0])) {
5003 value++;
5004 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005005
Radek Krejci0d7b2472016-02-12 11:11:03 +01005006 if (!strcmp(value, "unbounded")) {
5007 llist->max = 0;
5008 } else {
5009 /* convert it to uint32_t */
5010 errno = 0;
5011 endptr = NULL;
5012 val = strtoul(value, &endptr, 10);
5013 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005014 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005015 goto error;
5016 }
5017 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005018 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005019 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5020 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005021 goto error;
5022 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 }
Radek Krejci5323b492017-01-16 15:40:11 +01005024
Radek Krejci8d6b7422017-02-03 14:42:13 +01005025 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01005026 goto error;
5027 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005028 } else if (!strcmp(sub->name, "when")) {
5029 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005030 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005031 goto error;
5032 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005033
Radek Krejci5323b492017-01-16 15:40:11 +01005034 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005035 if (!llist->when) {
5036 goto error;
5037 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005038 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005039 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005040 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005041 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005042
Michal Vasko88c29542015-11-27 14:57:53 +01005043 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005046 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005047 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005048 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 goto error;
5050 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005052 /* middle part - process nodes with cardinality of 0..n */
5053 if (c_must) {
5054 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005055 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005056 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005057 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005058 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005059 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005060 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005061 if (c_dflt) {
5062 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005063 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005064 }
Radek Krejcie534c132016-11-23 13:32:31 +01005065 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005066 /* some extensions may be already present from the substatements */
5067 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005068 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005069 retval->ext = reallocated;
5070
5071 /* init memory */
5072 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005073 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005074
Radek Krejcie534c132016-11-23 13:32:31 +01005075 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5076 if (strcmp(sub->ns->value, LY_NSYIN)) {
5077 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005078 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 +01005079 retval->ext_size++;
5080 if (r) {
5081 goto error;
5082 }
5083 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005084 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005085 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005086 if (r) {
5087 goto error;
5088 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005089 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005090 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005091 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005092 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005093 goto error;
5094 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005095 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005096 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005097
Radek Krejciac1a52c2016-09-15 14:42:40 +02005098 /* check for duplicity in case of configuration data,
5099 * in case of status data duplicities are allowed */
5100 if (llist->flags & LYS_CONFIG_W) {
5101 for (r = 0; r < llist->dflt_size; r++) {
5102 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005103 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5104 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005105 goto error;
5106 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005107 }
5108 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005109 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005110 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005111 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005112
Radek Krejcicbb473e2016-09-16 14:48:32 +02005113 /* finalize type parsing */
5114 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5115 llist->type.der = NULL;
5116 goto error;
5117 }
5118
Radek Krejcid5a5c282016-08-15 15:38:08 +02005119 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005120 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5121 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005122 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5123 goto error;
5124 }
5125
5126 /* check default value (if not defined, there still could be some restrictions
5127 * that need to be checked against a default value from a derived type) */
5128 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko6a057782018-03-09 13:24:33 +01005129 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005130 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5131 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005132 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005133 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005134 }
5135
Michal Vasko508a50d2016-09-07 14:50:33 +02005136 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005137 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005138 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005139 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005140 goto error;
5141 }
5142 } else {
5143 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5144 goto error;
5145 }
5146 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005147 }
5148
PavolVican92f23622017-12-12 13:35:56 +01005149 for (r = 0; r < retval->ext_size; ++r) {
5150 /* set flag, which represent LYEXT_OPT_VALID */
5151 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005152 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005153 break;
5154 }
5155 }
5156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005157 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005158
5159error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005160 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005162}
5163
Michal Vasko0d343d12015-08-24 14:57:36 +02005164/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005165static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005166read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005167 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005168{
Michal Vasko53b7da02018-02-13 15:28:42 +01005169 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005170 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005171 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005173 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005174 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005175 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005176 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 char *auxs;
5178 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005179 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 /* init */
5182 memset(&root, 0, sizeof root);
5183 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005186 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005187
Radek Krejci76512572015-08-04 09:47:08 +02005188 list->nodetype = LYS_LIST;
5189 list->prev = (struct lys_node *)list;
5190 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005191
Radek Krejci07d0fb92017-01-13 14:11:05 +01005192 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005193 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5194 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5195 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005196 goto error;
5197 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005198
Michal Vasko3e3228d2017-02-24 14:55:32 +01005199 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005200
Radek Krejcic189a952016-07-11 15:27:07 +02005201 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005202 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005203 goto error;
5204 }
5205
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005206 /* process list's specific children */
5207 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005208 if (strcmp(sub->ns->value, LY_NSYIN)) {
5209 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005210 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005211 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005212 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005214 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005215 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005216 !strcmp(sub->name, "leaf-list") ||
5217 !strcmp(sub->name, "leaf") ||
5218 !strcmp(sub->name, "list") ||
5219 !strcmp(sub->name, "choice") ||
5220 !strcmp(sub->name, "uses") ||
5221 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005222 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005223 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005224 !strcmp(sub->name, "action") ||
5225 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005226 lyxml_unlink_elem(ctx, sub, 2);
5227 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005229 /* array counters */
5230 } else if (!strcmp(sub->name, "key")) {
5231 /* check cardinality 0..1 */
5232 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005233 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005234 goto error;
5235 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005237 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005238 GETVAL(ctx, value, sub, "value");
5239 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005240 while ((value = strpbrk(value, " \t\n"))) {
5241 list->keys_size++;
5242 while (isspace(*value)) {
5243 value++;
5244 }
5245 }
5246 list->keys_size++;
5247 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005248 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005249
Radek Krejci8d6b7422017-02-03 14:42:13 +01005250 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005251 goto error;
5252 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005253 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005255 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005256 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005257 lyxml_unlink_elem(ctx, sub, 2);
5258 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005260 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 c_tpdf++;
5262 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005263 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005265 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005266 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005267 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 /* optional stetments */
5270 } else if (!strcmp(sub->name, "ordered-by")) {
5271 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005272 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 goto error;
5274 }
5275 /* just checking the flags in llist is not sufficient, we would
5276 * allow multiple ordered-by statements with the "system" value
5277 */
5278 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005279
Radek Krejci1574a8d2015-08-03 14:16:52 +02005280 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5282 * state data
5283 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005284 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 continue;
5286 }
Radek Krejci345ad742015-06-03 11:04:18 +02005287
Michal Vasko53b7da02018-02-13 15:28:42 +01005288 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005290 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005291 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005292 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005294 } /* else system is the default value, so we can ignore it */
5295
Radek Krejci8d6b7422017-02-03 14:42:13 +01005296 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005297 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005299 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 } else if (!strcmp(sub->name, "min-elements")) {
5301 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005302 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005303 goto error;
5304 }
5305 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005306
Michal Vasko53b7da02018-02-13 15:28:42 +01005307 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 while (isspace(value[0])) {
5309 value++;
5310 }
Radek Krejci345ad742015-06-03 11:04:18 +02005311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 /* convert it to uint32_t */
5313 errno = 0;
5314 auxs = NULL;
5315 val = strtoul(value, &auxs, 10);
5316 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005317 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 goto error;
5319 }
5320 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005321 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005322 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5323 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5324 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005325 goto error;
5326 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005327 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005328 goto error;
5329 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005330 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005331 } else if (!strcmp(sub->name, "max-elements")) {
5332 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005333 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 goto error;
5335 }
5336 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005337
Michal Vasko53b7da02018-02-13 15:28:42 +01005338 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005339 while (isspace(value[0])) {
5340 value++;
5341 }
Radek Krejci345ad742015-06-03 11:04:18 +02005342
Radek Krejci0d7b2472016-02-12 11:11:03 +01005343 if (!strcmp(value, "unbounded")) {
5344 list->max = 0;;
5345 } else {
5346 /* convert it to uint32_t */
5347 errno = 0;
5348 auxs = NULL;
5349 val = strtoul(value, &auxs, 10);
5350 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005351 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005352 goto error;
5353 }
5354 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005355 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005356 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5357 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005358 goto error;
5359 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005361 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005362 goto error;
5363 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005364 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005365 } else if (!strcmp(sub->name, "when")) {
5366 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005367 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005368 goto error;
5369 }
5370
Radek Krejci5323b492017-01-16 15:40:11 +01005371 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005372 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005373 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005374 goto error;
5375 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005376 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005377 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005378 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005379 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005380 }
5381 }
Radek Krejci345ad742015-06-03 11:04:18 +02005382
Michal Vaskoe022a562016-09-27 14:24:15 +02005383 /* check - if list is configuration, key statement is mandatory
5384 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005385 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005386 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005387 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005388 goto error;
5389 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005391 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5392 if (c_tpdf) {
5393 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005394 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005395 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005396 if (c_must) {
5397 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005398 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005399 }
5400 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005401 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005402 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005403 }
Radek Krejcie534c132016-11-23 13:32:31 +01005404 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005405 /* some extensions may be already present from the substatements */
5406 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005407 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005408 retval->ext = reallocated;
5409
5410 /* init memory */
5411 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005412 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005413
Radek Krejcie534c132016-11-23 13:32:31 +01005414 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5415 if (strcmp(sub->ns->value, LY_NSYIN)) {
5416 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005417 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 +01005418 retval->ext_size++;
5419 if (r) {
5420 goto error;
5421 }
5422 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005423 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5424 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 if (r) {
5426 goto error;
5427 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005428 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005429 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005430 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005431 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005432 goto error;
5433 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005434 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005435 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005436 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005437 if (r) {
5438 goto error;
5439 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005440 }
5441 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 /* last part - process data nodes */
5444 LY_TREE_FOR_SAFE(root.child, next, sub) {
5445 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005446 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005447 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005448 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005449 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005450 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005451 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005452 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005454 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005455 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005456 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005457 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005458 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005459 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005460 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005461 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005462 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005463 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005464 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005465 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005466 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005467 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005468 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005469 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005470 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005471 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005472 goto error;
5473 }
Radek Krejci73adb602015-07-02 18:07:40 +02005474
Michal Vasko53b7da02018-02-13 15:28:42 +01005475 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005477
Radek Krejci5c08a992016-11-02 13:30:04 +01005478 if (list->keys_str) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02005479 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005480 goto error;
5481 }
5482 } /* 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 +02005483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005484 /* process unique statements */
5485 if (c_uniq) {
5486 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005487 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005488
Radek Krejci461efb92016-02-12 15:52:18 +01005489 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5490 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5491 list->unique_size++;
5492 if (r) {
5493 goto error;
5494 }
5495
Radek Krejci8d6b7422017-02-03 14:42:13 +01005496 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005497 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5498 goto error;
5499 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005500 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005501 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005502 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005503
Michal Vasko508a50d2016-09-07 14:50:33 +02005504 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005505 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005506 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005507 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005508 goto error;
5509 }
5510 } else {
5511 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5512 goto error;
5513 }
5514 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005515 }
5516
PavolVican92f23622017-12-12 13:35:56 +01005517 for (r = 0; r < retval->ext_size; ++r) {
5518 /* set flag, which represent LYEXT_OPT_VALID */
5519 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005520 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005521 break;
5522 }
5523 }
5524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005525 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005526
5527error:
5528
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005529 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005530 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005531 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005532 }
5533 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005534 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005535 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005537 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005538}
5539
Michal Vasko0d343d12015-08-24 14:57:36 +02005540/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005541static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005542read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005543 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005544{
Michal Vasko53b7da02018-02-13 15:28:42 +01005545 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005546 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005547 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005548 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005549 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005550 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005551 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005552 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005553 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005555 /* init */
5556 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005558 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005559 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005560
Radek Krejci76512572015-08-04 09:47:08 +02005561 cont->nodetype = LYS_CONTAINER;
5562 cont->prev = (struct lys_node *)cont;
5563 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005564
Radek Krejci07d0fb92017-01-13 14:11:05 +01005565 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005566 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5567 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5568 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005569 goto error;
5570 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005571
Michal Vasko3e3228d2017-02-24 14:55:32 +01005572 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005573
Radek Krejcic189a952016-07-11 15:27:07 +02005574 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005575 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005576 goto error;
5577 }
5578
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005579 /* process container's specific children */
5580 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005581 if (strcmp(sub->ns->value, LY_NSYIN)) {
5582 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005583 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005584 c_ext++;
5585 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005586 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005587 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005588 goto error;
5589 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005590 GETVAL(ctx, value, sub, "value");
5591 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005592
Radek Krejci8d6b7422017-02-03 14:42:13 +01005593 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005594 goto error;
5595 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005596 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005597 } else if (!strcmp(sub->name, "when")) {
5598 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005599 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005600 goto error;
5601 }
5602
Radek Krejci5323b492017-01-16 15:40:11 +01005603 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005604 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005605 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005606 goto error;
5607 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005608 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 /* data statements */
5611 } else if (!strcmp(sub->name, "container") ||
5612 !strcmp(sub->name, "leaf-list") ||
5613 !strcmp(sub->name, "leaf") ||
5614 !strcmp(sub->name, "list") ||
5615 !strcmp(sub->name, "choice") ||
5616 !strcmp(sub->name, "uses") ||
5617 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005618 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005619 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005620 !strcmp(sub->name, "action") ||
5621 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005622 lyxml_unlink_elem(ctx, sub, 2);
5623 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005625 /* array counters */
5626 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005627 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005628 c_tpdf++;
5629 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005630 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005631 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005632 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005633 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005634 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005635 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005636 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005637 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005638 }
5639 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005641 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5642 if (c_tpdf) {
5643 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005644 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005645 }
5646 if (c_must) {
5647 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005648 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005649 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005650 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005651 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005652 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005653 }
Radek Krejcie534c132016-11-23 13:32:31 +01005654 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005655 /* some extensions may be already present from the substatements */
5656 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005657 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005658 retval->ext = reallocated;
5659
5660 /* init memory */
5661 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005662 }
Radek Krejci800af702015-06-02 13:46:01 +02005663
Radek Krejcie534c132016-11-23 13:32:31 +01005664 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5665 if (strcmp(sub->ns->value, LY_NSYIN)) {
5666 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005667 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 +01005668 retval->ext_size++;
5669 if (r) {
5670 goto error;
5671 }
5672 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005673 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5674 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005675 if (r) {
5676 goto error;
5677 }
5678 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005679 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005680 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005681 if (r) {
5682 goto error;
5683 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005684 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005685 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005686 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005687 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005688 goto error;
5689 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005690 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005691 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005692
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005693 /* last part - process data nodes */
5694 LY_TREE_FOR_SAFE(root.child, next, sub) {
5695 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005696 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005697 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005698 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005699 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005700 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005701 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005702 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005703 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005704 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005705 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005706 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005707 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005708 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005709 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005710 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005711 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005712 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005713 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005714 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005715 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005716 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005717 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005718 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005719 goto error;
5720 }
Radek Krejci73adb602015-07-02 18:07:40 +02005721
Michal Vasko53b7da02018-02-13 15:28:42 +01005722 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005723 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005724
Michal Vasko508a50d2016-09-07 14:50:33 +02005725 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005726 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005727 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005728 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005729 goto error;
5730 }
5731 } else {
5732 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5733 goto error;
5734 }
5735 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005736 }
5737
PavolVican92f23622017-12-12 13:35:56 +01005738 for (r = 0; r < retval->ext_size; ++r) {
5739 /* set flag, which represent LYEXT_OPT_VALID */
5740 if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005741 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005742 break;
5743 }
5744 }
5745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005746 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005747
5748error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005749 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005750 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005751 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005752 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005753 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005754}
5755
Michal Vasko0d343d12015-08-24 14:57:36 +02005756/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005757static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005758read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005759 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005760{
Michal Vasko53b7da02018-02-13 15:28:42 +01005761 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005762 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005763 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005764 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005765 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005766 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005767 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005768 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005770 /* init */
5771 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005773 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005774 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005775
Radek Krejci76512572015-08-04 09:47:08 +02005776 grp->nodetype = LYS_GROUPING;
5777 grp->prev = (struct lys_node *)grp;
5778 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005779
Radek Krejci07d0fb92017-01-13 14:11:05 +01005780 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005781 goto error;
5782 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005783
Michal Vasko3e3228d2017-02-24 14:55:32 +01005784 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005785
Radek Krejcic189a952016-07-11 15:27:07 +02005786 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005787 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005788 goto error;
5789 }
5790
Radek Krejci1d82ef62015-08-07 14:44:40 +02005791 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005792 if (strcmp(sub->ns->value, LY_NSYIN)) {
5793 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005794 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005795 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005797 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005798 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005799 !strcmp(sub->name, "leaf-list") ||
5800 !strcmp(sub->name, "leaf") ||
5801 !strcmp(sub->name, "list") ||
5802 !strcmp(sub->name, "choice") ||
5803 !strcmp(sub->name, "uses") ||
5804 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005805 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005806 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005807 !strcmp(sub->name, "action") ||
5808 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005809 lyxml_unlink_elem(ctx, sub, 2);
5810 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005812 /* array counters */
5813 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005814 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005815 c_tpdf++;
5816 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005817 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005818 goto error;
5819 }
5820 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005822 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5823 if (c_tpdf) {
5824 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005825 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005826 }
Radek Krejcie534c132016-11-23 13:32:31 +01005827 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005828 /* some extensions may be already present from the substatements */
5829 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005830 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005831 retval->ext = reallocated;
5832
5833 /* init memory */
5834 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005835 }
Radek Krejcie534c132016-11-23 13:32:31 +01005836 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5837 if (strcmp(sub->ns->value, LY_NSYIN)) {
5838 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005839 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 +01005840 retval->ext_size++;
5841 if (r) {
5842 goto error;
5843 }
5844 } else {
5845 /* typedef */
5846 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5847 grp->tpdf_size++;
5848 if (r) {
5849 goto error;
5850 }
5851 }
5852 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005854 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005855 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005856 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005857 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005858 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005859 LY_TREE_FOR_SAFE(root.child, next, sub) {
5860 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005861 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005862 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005863 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005864 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005865 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005866 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005867 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005868 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005869 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005870 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005871 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005872 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005873 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005874 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005875 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005876 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005877 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005878 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005879 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005880 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005881 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005882 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005883 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005884 goto error;
5885 }
Radek Krejci73adb602015-07-02 18:07:40 +02005886
Michal Vasko53b7da02018-02-13 15:28:42 +01005887 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005888 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005890 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005891
5892error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005893 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005894 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005895 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005896 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005897 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005898}
5899
Michal Vasko0d343d12015-08-24 14:57:36 +02005900/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005901static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005902read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005903 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005904{
Michal Vasko53b7da02018-02-13 15:28:42 +01005905 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005906 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005907 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005908 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005909 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005910 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005911 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005912
Radek Krejcie0674f82015-06-15 13:58:51 +02005913 /* init */
5914 memset(&root, 0, sizeof root);
5915
Michal Vasko38d01f72015-06-15 09:41:06 +02005916 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005917 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005918 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005919
5920 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005921 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005922 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005923 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005924 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005925 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005926 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005927 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005928 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005929 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005930 }
5931
Radek Krejci76512572015-08-04 09:47:08 +02005932 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005933 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005934
Michal Vasko3e3228d2017-02-24 14:55:32 +01005935 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005936
Radek Krejcic189a952016-07-11 15:27:07 +02005937 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005938 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005939 goto error;
5940 }
5941
Michal Vasko38d01f72015-06-15 09:41:06 +02005942 /* data statements */
5943 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005944 if (!sub->ns) {
5945 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005946 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005947 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005948 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005949 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005950 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005951 c_ext++;
5952 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005953 !strcmp(sub->name, "leaf-list") ||
5954 !strcmp(sub->name, "leaf") ||
5955 !strcmp(sub->name, "list") ||
5956 !strcmp(sub->name, "choice") ||
5957 !strcmp(sub->name, "uses") ||
5958 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005959 !strcmp(sub->name, "anyxml") ||
5960 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005961 lyxml_unlink_elem(ctx, sub, 2);
5962 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005964 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005965 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005966 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02005967 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005968 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005969
Radek Krejci1a31efe2016-07-29 11:04:16 +02005970 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005971 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02005972 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02005973 c_must++;
5974
Michal Vasko38d01f72015-06-15 09:41:06 +02005975 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005976 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005977 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005978 }
5979 }
5980
5981 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5982 if (c_tpdf) {
5983 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005984 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005985 }
Radek Krejci19332802016-07-29 10:39:46 +02005986 if (c_must) {
5987 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005988 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02005989 }
Radek Krejcie534c132016-11-23 13:32:31 +01005990 if (c_ext) {
5991 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005992 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01005993 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005994
Radek Krejcie534c132016-11-23 13:32:31 +01005995 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5996 if (strcmp(sub->ns->value, LY_NSYIN)) {
5997 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005998 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 +01005999 retval->ext_size++;
6000 if (r) {
6001 goto error;
6002 }
6003 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006004 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006005 inout->must_size++;
6006 if (r) {
6007 goto error;
6008 }
6009 } else { /* typedef */
6010 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
6011 inout->tpdf_size++;
6012 if (r) {
6013 goto error;
6014 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006015 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006016 }
6017
6018 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006019 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02006020 LY_TREE_FOR_SAFE(root.child, next, sub) {
6021 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006022 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006023 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006024 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006025 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006026 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006027 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006028 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006029 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006030 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006031 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006032 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006033 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006034 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006035 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006036 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006037 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006038 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006039 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006040 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006041 goto error;
6042 }
Radek Krejci73adb602015-07-02 18:07:40 +02006043
Michal Vasko53b7da02018-02-13 15:28:42 +01006044 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006045 }
6046
Michal Vasko508a50d2016-09-07 14:50:33 +02006047 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006048 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006049 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006050 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006051 goto error;
6052 }
6053 } else {
6054 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6055 goto error;
6056 }
6057 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006058 }
6059
Michal Vasko38d01f72015-06-15 09:41:06 +02006060 return retval;
6061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006062error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006063 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006064 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006065 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006066 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006067 return NULL;
6068}
6069
Michal Vasko0d343d12015-08-24 14:57:36 +02006070/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006071static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006072read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006073 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006074{
Michal Vasko53b7da02018-02-13 15:28:42 +01006075 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006076 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006077 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006078 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006079 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006080 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006081 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006082 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006083
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006084 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006085 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006086 return NULL;
6087 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006088
Michal Vaskoc6551b32015-06-16 10:51:43 +02006089 memset(&root, 0, sizeof root);
6090
Michal Vasko0ea41032015-06-16 08:53:55 +02006091 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006092 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006093
Radek Krejci76512572015-08-04 09:47:08 +02006094 notif->nodetype = LYS_NOTIF;
6095 notif->prev = (struct lys_node *)notif;
6096 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006097
Radek Krejci07d0fb92017-01-13 14:11:05 +01006098 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006099 goto error;
6100 }
6101
Michal Vasko3e3228d2017-02-24 14:55:32 +01006102 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006103
Radek Krejcic189a952016-07-11 15:27:07 +02006104 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006105 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006106 goto error;
6107 }
6108
Michal Vasko0ea41032015-06-16 08:53:55 +02006109 /* process rpc's specific children */
6110 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006111 if (strcmp(sub->ns->value, LY_NSYIN)) {
6112 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006113 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006114 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006115 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006116
Michal Vasko0ea41032015-06-16 08:53:55 +02006117 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006118 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006119 !strcmp(sub->name, "leaf-list") ||
6120 !strcmp(sub->name, "leaf") ||
6121 !strcmp(sub->name, "list") ||
6122 !strcmp(sub->name, "choice") ||
6123 !strcmp(sub->name, "uses") ||
6124 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006125 !strcmp(sub->name, "anyxml") ||
6126 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006127 lyxml_unlink_elem(ctx, sub, 2);
6128 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006130 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006131 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006132 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006133 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006134 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006135 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006136 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006137 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006138 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006139 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006140 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006141 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006142 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006143 }
6144 }
6145
6146 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6147 if (c_tpdf) {
6148 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006149 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006150 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006151 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006152 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006153 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006154 }
Radek Krejci19332802016-07-29 10:39:46 +02006155 if (c_must) {
6156 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006157 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006158 }
Radek Krejcie534c132016-11-23 13:32:31 +01006159 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006160 /* some extensions may be already present from the substatements */
6161 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006162 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006163 retval->ext = reallocated;
6164
6165 /* init memory */
6166 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006167 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006168
Radek Krejcie534c132016-11-23 13:32:31 +01006169 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6170 if (strcmp(sub->ns->value, LY_NSYIN)) {
6171 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006172 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 +01006173 retval->ext_size++;
6174 if (r) {
6175 goto error;
6176 }
6177 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006178 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6179 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006180 if (r) {
6181 goto error;
6182 }
Radek Krejci96299152016-06-22 10:17:50 +02006183 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006184 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006185 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006186 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006187 goto error;
6188 }
Radek Krejci19332802016-07-29 10:39:46 +02006189 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006190 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006191 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006192 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006193 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006194 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006195 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006196 }
6197
6198 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006199 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006200 LY_TREE_FOR_SAFE(root.child, next, sub) {
6201 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006202 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006203 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006204 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006205 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006206 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006207 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006208 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006209 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006210 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006211 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006212 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006213 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006214 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006215 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006216 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006217 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006218 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006219 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006220 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006221 goto error;
6222 }
Radek Krejci73adb602015-07-02 18:07:40 +02006223
Michal Vasko53b7da02018-02-13 15:28:42 +01006224 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006225 }
6226
Michal Vasko508a50d2016-09-07 14:50:33 +02006227 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006228 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006229 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006230 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006231 goto error;
6232 }
6233 } else {
6234 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6235 goto error;
6236 }
6237 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006238 }
6239
Michal Vasko0ea41032015-06-16 08:53:55 +02006240 return retval;
6241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006242error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006243 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006244 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006245 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006246 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006247 return NULL;
6248}
6249
Michal Vasko0d343d12015-08-24 14:57:36 +02006250/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006251static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006252read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006253 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006254{
Michal Vasko53b7da02018-02-13 15:28:42 +01006255 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006256 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006257 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006258 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006259 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006260 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006261 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006262 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006263
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006264 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006265 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006266 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006267 return NULL;
6268 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006269 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006270 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006271 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006272 LOGVAL(ctx, LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006273 return NULL;
6274 }
6275 }
6276 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006277
Radek Krejcie0674f82015-06-15 13:58:51 +02006278 /* init */
6279 memset(&root, 0, sizeof root);
6280
Michal Vasko38d01f72015-06-15 09:41:06 +02006281 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006282 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006283
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006284 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006285 rpc->prev = (struct lys_node *)rpc;
6286 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006287
Radek Krejci07d0fb92017-01-13 14:11:05 +01006288 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006289 goto error;
6290 }
6291
Michal Vasko3e3228d2017-02-24 14:55:32 +01006292 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006293
Radek Krejcic189a952016-07-11 15:27:07 +02006294 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006295 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006296 goto error;
6297 }
6298
Michal Vasko38d01f72015-06-15 09:41:06 +02006299 /* process rpc's specific children */
6300 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006301 if (strcmp(sub->ns->value, LY_NSYIN)) {
6302 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006303 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006304 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006305 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006306 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006307 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006308 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006309 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006310 goto error;
6311 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006312 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006313 lyxml_unlink_elem(ctx, sub, 2);
6314 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006315 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006316 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006317 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006318 goto error;
6319 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006320 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006321 lyxml_unlink_elem(ctx, sub, 2);
6322 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006324 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006325 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006326 lyxml_unlink_elem(ctx, sub, 2);
6327 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006329 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006330 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006331 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006332 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006333 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006334 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006335 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006336 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006337 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006338 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006339 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006340 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006341 }
6342 }
6343
6344 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6345 if (c_tpdf) {
6346 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006347 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006348 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006349 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006350 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006351 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006352 }
Radek Krejcie534c132016-11-23 13:32:31 +01006353 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006354 /* some extensions may be already present from the substatements */
6355 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006356 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006357 retval->ext = reallocated;
6358
6359 /* init memory */
6360 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006361 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006362
Radek Krejcie534c132016-11-23 13:32:31 +01006363 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6364 if (strcmp(sub->ns->value, LY_NSYIN)) {
6365 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006366 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 +01006367 retval->ext_size++;
6368 if (r) {
6369 goto error;
6370 }
6371 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006372 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6373 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006374 if (r) {
6375 goto error;
6376 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006377 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006378 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006379 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006380 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006381 goto error;
6382 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006383 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006384 }
6385
6386 /* last part - process data nodes */
6387 LY_TREE_FOR_SAFE(root.child, next, sub) {
6388 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006389 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006390 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006391 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006392 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006393 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006394 goto error;
6395 }
Radek Krejci73adb602015-07-02 18:07:40 +02006396
Michal Vasko53b7da02018-02-13 15:28:42 +01006397 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006398 }
6399
Michal Vasko38d01f72015-06-15 09:41:06 +02006400 return retval;
6401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006402error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006403 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006404 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006405 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006406 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006407 return NULL;
6408}
6409
Michal Vasko0d343d12015-08-24 14:57:36 +02006410/* logs directly
6411 *
Radek Krejci74705112015-06-05 10:25:44 +02006412 * resolve - referenced grouping should be bounded to the namespace (resolved)
6413 * only when uses does not appear in grouping. In a case of grouping's uses,
6414 * we just get information but we do not apply augment or refine to it.
6415 */
Radek Krejci76512572015-08-04 09:47:08 +02006416static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006417read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6418 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006419{
Michal Vasko53b7da02018-02-13 15:28:42 +01006420 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006421 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006422 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006423 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006424 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006425 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006426 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006427 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006429 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006430 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006431
Radek Krejci76512572015-08-04 09:47:08 +02006432 uses->nodetype = LYS_USES;
6433 uses->prev = (struct lys_node *)uses;
6434 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006435
Michal Vasko53b7da02018-02-13 15:28:42 +01006436 GETVAL(ctx, value, yin, "name");
6437 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006438
Radek Krejci07d0fb92017-01-13 14:11:05 +01006439 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006440 goto error;
6441 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006442
Michal Vasko3e3228d2017-02-24 14:55:32 +01006443 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006444
Radek Krejcic189a952016-07-11 15:27:07 +02006445 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006446 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006447 goto error;
6448 }
6449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006450 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006451 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006452 if (strcmp(sub->ns->value, LY_NSYIN)) {
6453 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006454 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006455 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006456 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006457 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006458 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006459 c_ref++;
6460 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006461 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006462 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006463 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006464 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006465 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006466 } else if (!strcmp(sub->name, "when")) {
6467 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006468 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006469 goto error;
6470 }
6471
Radek Krejci5323b492017-01-16 15:40:11 +01006472 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006473 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006474 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006475 goto error;
6476 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006477 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006478 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006479 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006480 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006481 }
6482 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006484 /* process properties with cardinality 0..n */
6485 if (c_ref) {
6486 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006487 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006488 }
6489 if (c_aug) {
6490 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006491 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006492 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006493 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006494 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006495 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006496 }
Radek Krejcie534c132016-11-23 13:32:31 +01006497 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006498 /* some extensions may be already present from the substatements */
6499 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006500 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006501 retval->ext = reallocated;
6502
6503 /* init memory */
6504 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006505 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006506
Radek Krejcie534c132016-11-23 13:32:31 +01006507 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6508 if (strcmp(sub->ns->value, LY_NSYIN)) {
6509 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006510 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 +01006511 retval->ext_size++;
6512 if (r) {
6513 goto error;
6514 }
6515 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006516 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006517 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006518 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006519 goto error;
6520 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006521 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006522 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006523 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006524 if (r) {
6525 goto error;
6526 }
6527 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006528 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006529 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006530 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006531 goto error;
6532 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006533 }
6534 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006535
Radek Krejci48464ed2016-03-17 15:44:09 +01006536 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006537 goto error;
6538 }
Radek Krejci74705112015-06-05 10:25:44 +02006539
Michal Vasko508a50d2016-09-07 14:50:33 +02006540 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006541 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006542 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006543 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006544 goto error;
6545 }
6546 } else {
6547 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6548 goto error;
6549 }
6550 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006551 }
6552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006553 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006554
6555error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006556 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006557 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006558}
6559
Michal Vasko0d343d12015-08-24 14:57:36 +02006560/* logs directly
6561 *
6562 * common code for yin_read_module() and yin_read_submodule()
6563 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006564static int
Radek Krejcic071c542016-01-27 14:57:51 +01006565read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6566 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006567{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006568 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006569 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006570 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006571 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006572 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006573 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006574 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006575 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6576 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6577 int substmt_group;
6578 /* just remember last substatement for logging */
6579 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006580 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006581 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;
6582 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006583 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006584
Radek Krejcic071c542016-01-27 14:57:51 +01006585 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006586 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006588 /* init */
6589 memset(&root, 0, sizeof root);
6590 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006591 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006592 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006593 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006595 /*
6596 * in the first run, we process elements with cardinality of 1 or 0..1 and
6597 * count elements with cardinality 0..n. Data elements (choices, containers,
6598 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6599 * need have all top-level and groupings already prepared at that time. In
6600 * the middle loop, we process other elements with carinality of 0..n since
6601 * we need to allocate arrays to store them.
6602 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006603 substmt_group = 0;
6604 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006605 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006606 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006607 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006608 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006609 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006610 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006611 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006612 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006613 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006614 lyxml_unlink_elem(ctx, child, 2);
6615 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006616 c_extinst++;
6617 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006618 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006619 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6620 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006621 child->name, substmt_prev);
6622 goto error;
6623 }
6624
PavolVican9e81c6a2017-02-09 13:09:07 +01006625 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006626 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006627 goto error;
6628 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006629 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006630 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006631
Radek Krejci8d6b7422017-02-03 14:42:13 +01006632 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006633 goto error;
6634 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006635 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006636
6637 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006638 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006639 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006640 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6641 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006642 child->name, substmt_prev);
6643 goto error;
6644 }
6645
PavolVican9e81c6a2017-02-09 13:09:07 +01006646 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006647 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006648 goto error;
6649 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006650 GETVAL(ctx, value, child, "value");
6651 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006652 goto error;
6653 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006654 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006655
Radek Krejci8d6b7422017-02-03 14:42:13 +01006656 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006657 goto error;
6658 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006659 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006660
6661 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006662 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006663 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006664 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6665 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006666 child->name, substmt_prev);
6667 goto error;
6668 }
6669
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006670 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006671 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006672 goto error;
6673 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006674 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006675 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006676 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006677 goto error;
6678 }
Radek Krejcif3886932015-06-04 17:36:06 +02006679
Radek Krejci8d6b7422017-02-03 14:42:13 +01006680 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006681 goto error;
6682 }
6683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006684 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006685 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006686 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006687 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006688 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006689 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006690 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006691 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006692 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006693 goto error;
6694 }
6695 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006696 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006697 /* check here differs from a generic prefix check, since this prefix
6698 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006699 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006700 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006701 goto error;
6702 }
Radek Krejcic071c542016-01-27 14:57:51 +01006703 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006704
Radek Krejci8d6b7422017-02-03 14:42:13 +01006705 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 +01006706 goto error;
6707 }
6708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006709 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006710 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006711
Michal Vasko5de8a022017-02-08 10:57:26 +01006712 substmt_prev = "belongs-to";
6713
Radek Krejcieb00f512015-07-01 16:44:58 +02006714 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006715 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006716 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006717 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6718 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006719 child->name, substmt_prev);
6720 goto error;
6721 }
6722 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006723 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006724 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006725 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006726
6727 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006728 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006729 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006730 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6731 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006732 child->name, substmt_prev);
6733 goto error;
6734 }
6735 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006736 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006737 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006738 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006739
PavolVican9e81c6a2017-02-09 13:09:07 +01006740 lyxml_unlink_elem(ctx, child, 2);
6741 lyxml_add_child(ctx, &revs, child);
6742
Michal Vasko5de8a022017-02-08 10:57:26 +01006743 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006744 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006745 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006746 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006747 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006748 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006749
6750 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006751 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006752 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006753 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006754 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006755 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006756
6757 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006758 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006759 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006760 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6761 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006762 child->name, substmt_prev);
6763 goto error;
6764 }
6765 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006766 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006767 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006768 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006769
6770 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006771 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006772 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006773 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006774 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006775 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006776 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006777 lyxml_unlink_elem(ctx, child, 2);
6778 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006779
Michal Vasko5de8a022017-02-08 10:57:26 +01006780 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006781 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006782 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006783 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006784 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006785 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006786
Michal Vasko5de8a022017-02-08 10:57:26 +01006787 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006789 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006790 } else if (!strcmp(child->name, "container") ||
6791 !strcmp(child->name, "leaf-list") ||
6792 !strcmp(child->name, "leaf") ||
6793 !strcmp(child->name, "list") ||
6794 !strcmp(child->name, "choice") ||
6795 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006796 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006797 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006798 !strcmp(child->name, "rpc") ||
6799 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006800 substmt_group = 4;
6801
Radek Krejcic071c542016-01-27 14:57:51 +01006802 lyxml_unlink_elem(ctx, child, 2);
6803 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006804
Michal Vasko5de8a022017-02-08 10:57:26 +01006805 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006806 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006807 substmt_group = 4;
6808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006809 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006810 lyxml_unlink_elem(ctx, child, 2);
6811 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006812
Michal Vasko5de8a022017-02-08 10:57:26 +01006813 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006814 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006815 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006816 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006817 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6818 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006819 child->name, substmt_prev);
6820 goto error;
6821 }
6822 substmt_group = 2;
6823
Radek Krejcic071c542016-01-27 14:57:51 +01006824 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006825 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006826 goto error;
6827 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006828 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006829 goto error;
6830 }
Radek Krejcic071c542016-01-27 14:57:51 +01006831 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006832 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006833 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006834 goto error;
6835 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006836
6837 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006838 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006839 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006840 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6841 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006842 child->name, substmt_prev);
6843 goto error;
6844 }
6845 substmt_group = 2;
6846
Radek Krejcic071c542016-01-27 14:57:51 +01006847 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006848 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006849 goto error;
6850 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006851 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006852 goto error;
6853 }
Radek Krejcic071c542016-01-27 14:57:51 +01006854 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006855 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006856 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006857 goto error;
6858 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006859
6860 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006861 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006862 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006863 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6864 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006865 child->name, substmt_prev);
6866 goto error;
6867 }
6868 substmt_group = 2;
6869
Radek Krejcic071c542016-01-27 14:57:51 +01006870 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006871 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006872 goto error;
6873 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006874 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006875 goto error;
6876 }
Radek Krejcic071c542016-01-27 14:57:51 +01006877 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006878 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006879 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006880 goto error;
6881 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006882
6883 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006884 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006885 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006886 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6887 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006888 child->name, substmt_prev);
6889 goto error;
6890 }
6891 substmt_group = 2;
6892
Radek Krejcic071c542016-01-27 14:57:51 +01006893 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006894 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006895 goto error;
6896 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006897 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006898 goto error;
6899 }
Radek Krejcic071c542016-01-27 14:57:51 +01006900 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006901 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006902 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006903 goto error;
6904 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006905
6906 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006907 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006908 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006909 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6910 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006911 child->name, substmt_prev);
6912 goto error;
6913 }
6914
Radek Krejcic071c542016-01-27 14:57:51 +01006915 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006916 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006917 goto error;
6918 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006919 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006920 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006921 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006922 goto error;
6923 }
Radek Krejcic071c542016-01-27 14:57:51 +01006924 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006925 if (!strcmp(value, "1")) {
6926 if (submodule) {
6927 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006928 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006929 goto error;
6930 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006931 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006932 } else {
6933 module->version = 1;
6934 }
6935 } else {
6936 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006937 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006938 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006939 goto error;
6940 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006941 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006942 } else {
6943 module->version = 2;
6944 }
6945 }
6946
Radek Krejci8d6b7422017-02-03 14:42:13 +01006947 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006948 goto error;
6949 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006950 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006951
Michal Vasko5de8a022017-02-08 10:57:26 +01006952 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006953 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006954 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006955 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006956 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006957 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006958
Michal Vasko5de8a022017-02-08 10:57:26 +01006959 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006960 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006961 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006962 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006963 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006964 c_dev++;
6965
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006966 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006967 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006968 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006969 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006970 }
6971 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006972
Radek Krejcic071c542016-01-27 14:57:51 +01006973 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006974 if (submodule) {
6975 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006976 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006977 goto error;
6978 }
6979 if (!version_flag) {
6980 /* check version compatibility with the main module */
6981 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006982 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006983 goto error;
6984 }
6985 }
6986 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006987 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006988 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006989 goto error;
6990 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006991 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006992 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006993 goto error;
6994 }
6995 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006997 /* allocate arrays for elements with cardinality of 0..n */
6998 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006999 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01007000 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007001 }
7002 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007003 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01007004 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007005 }
7006 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01007007 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01007008 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007009 }
7010 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01007011 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01007012 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007013 }
7014 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007015 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01007016 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007017 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007018 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01007019 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01007020 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007021 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02007022 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01007023 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007024 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007025 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007026 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007027 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007028 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007029 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007030 if (c_ext) {
7031 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007032 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007033 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007034
PavolVican9e81c6a2017-02-09 13:09:07 +01007035 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7036 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007037 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7038 trg->rev_size++;
7039 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007040 goto error;
7041 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007042
Radek Krejci7417a082017-02-16 11:07:59 +01007043 /* check uniqueness of the revision date - not required by RFC */
7044 for (i = 0; i < (trg->rev_size - 1); i++) {
7045 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007046 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007047 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007048 }
7049 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007050
7051 lyxml_free(ctx, child);
7052 }
7053
7054 /* check the module with respect to the context now */
7055 if (!submodule) {
7056 switch (lyp_ctx_check_module(module)) {
7057 case -1:
7058 goto error;
7059 case 0:
7060 break;
7061 case 1:
7062 /* it's already there */
7063 ret = 1;
7064 goto error;
7065 }
7066 }
7067
PavolVican92f23622017-12-12 13:35:56 +01007068 /* check first definition of extensions */
7069 if (c_ext) {
7070 LY_TREE_FOR_SAFE(yin->child, next, child) {
7071 if (!strcmp(child->name, "extension")) {
7072 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7073 trg->extensions_size++;
7074 if (r) {
7075 goto error;
7076 }
7077
7078 }
7079 }
7080 }
7081
PavolVican9e81c6a2017-02-09 13:09:07 +01007082 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007083 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007084 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007085 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007086 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007087 if (r) {
7088 goto error;
7089 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007090
Radek Krejci1d82ef62015-08-07 14:44:40 +02007091 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007092 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7093 trg->inc_size++;
7094 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007095 goto error;
7096 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007097
Radek Krejci1d82ef62015-08-07 14:44:40 +02007098 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007099 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7100 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007101 if (r) {
7102 goto error;
7103 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007104
Radek Krejci1d82ef62015-08-07 14:44:40 +02007105 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007106 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7107 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007108 if (r) {
7109 goto error;
7110 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007111
Radek Krejci1d82ef62015-08-07 14:44:40 +02007112 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007113 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7114 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007115 if (r) {
7116 goto error;
7117 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007118
Radek Krejci1d82ef62015-08-07 14:44:40 +02007119 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko0f437062018-06-08 15:52:39 +02007120 /* must be implemented in this case */
7121 trg->implemented = 1;
7122
Radek Krejcic071c542016-01-27 14:57:51 +01007123 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7124 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007125 if (r) {
7126 goto error;
7127 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007128 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007129 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007130
Radek Krejcie534c132016-11-23 13:32:31 +01007131 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007132 if (c_extinst) {
7133 /* some extensions may be already present from the substatements */
7134 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007135 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007136 trg->ext = reallocated;
7137
7138 /* init memory */
7139 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7140
7141 LY_TREE_FOR_SAFE(exts.child, next, child) {
7142 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7143 trg->ext_size++;
7144 if (r) {
7145 goto error;
7146 }
7147 }
Radek Krejcie534c132016-11-23 13:32:31 +01007148 }
7149
Radek Krejcif5be10f2015-06-16 13:29:36 +02007150 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007151 * refer to them. Submodule's data nodes are stored in the
7152 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007153 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007154 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007155 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007156 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007157 goto error;
7158 }
Radek Krejci74705112015-06-05 10:25:44 +02007159
Michal Vasko345da0a2015-12-02 10:35:55 +01007160 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007161 }
Radek Krejci74705112015-06-05 10:25:44 +02007162
Radek Krejcif5be10f2015-06-16 13:29:36 +02007163 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007164 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007165
Radek Krejci1d82ef62015-08-07 14:44:40 +02007166 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007167 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007168 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007169 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007170 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007171 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007172 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007173 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007174 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007175 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007176 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007177 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007178 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007179 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007180 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007181 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007182 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007183 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007184 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007185 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007186 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007187 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007188 goto error;
7189 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007190
Michal Vasko345da0a2015-12-02 10:35:55 +01007191 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007192 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007193
Michal Vasko2f7925f2015-10-21 15:06:56 +02007194 /* ... and finally augments (last, so we can augment our data, for instance) */
7195 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007196 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007197 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007198
Michal Vasko2f7925f2015-10-21 15:06:56 +02007199 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007200 goto error;
7201 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007202 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007203 }
7204
PavolVican9e81c6a2017-02-09 13:09:07 +01007205 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007206
7207error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007208 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007209 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007210 }
7211 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007212 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007213 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007214 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007215 lyxml_free(ctx, augs.child);
7216 }
7217 while (revs.child) {
7218 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007219 }
Radek Krejcie534c132016-11-23 13:32:31 +01007220 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007221 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007222 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007223
PavolVican9e81c6a2017-02-09 13:09:07 +01007224 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007225}
7226
Michal Vasko0d343d12015-08-24 14:57:36 +02007227/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007228struct lys_submodule *
7229yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007230{
Michal Vasko53b7da02018-02-13 15:28:42 +01007231 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007232 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007233 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007234 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007235
Michal Vasko53b7da02018-02-13 15:28:42 +01007236 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007237 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007238 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007239 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007241 /* check root element */
7242 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007243 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007244 goto error;
7245 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007246
Michal Vasko53b7da02018-02-13 15:28:42 +01007247 GETVAL(ctx, value, yin, "name");
7248 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007249 goto error;
7250 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007251
Michal Vasko5a721fd2016-02-16 12:16:48 +01007252 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007253 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007254
Michal Vasko53b7da02018-02-13 15:28:42 +01007255 submodule->ctx = ctx;
7256 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007257 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007258 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007259 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007260
Radek Krejci9e757e02017-03-08 17:18:09 +01007261 /* add into the list of processed modules */
7262 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7263 goto error;
7264 }
7265
Michal Vasko5a721fd2016-02-16 12:16:48 +01007266 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007267 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007268 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007269 goto error;
7270 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007271
Radek Krejci33fc4772017-01-26 16:00:35 +01007272 lyp_sort_revisions((struct lys_module *)submodule);
7273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007274 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007275 lyxml_free(ctx, yin);
7276 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007277
Michal Vasko5a721fd2016-02-16 12:16:48 +01007278 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007279 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007280
7281error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007282 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007283 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007284 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007285 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007286 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007287 }
7288
Michal Vasko53b7da02018-02-13 15:28:42 +01007289 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007290
Michal Vaskoa9728122018-01-16 14:00:13 +01007291 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007292 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007293 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7294 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007295 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007296 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007297}
7298
Michal Vasko0d343d12015-08-24 14:57:36 +02007299/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007300struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007301yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007302{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007303 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007304 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007305 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007306 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007307
Radek Krejcic071c542016-01-27 14:57:51 +01007308 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007309 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007311 /* check root element */
7312 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007313 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007314 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007315 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007316 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007318 goto error;
7319 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007320
Michal Vasko53b7da02018-02-13 15:28:42 +01007321 GETVAL(ctx, value, yin, "name");
7322 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007323 goto error;
7324 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007326 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007327 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007329 module->ctx = ctx;
7330 module->name = lydict_insert(ctx, value, strlen(value));
7331 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007332 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007333
Radek Krejci9e757e02017-03-08 17:18:09 +01007334 /* add into the list of processed modules */
7335 if (lyp_check_circmod_add(module)) {
7336 goto error;
7337 }
7338
Michal Vasko9f258e42016-02-11 11:36:27 +01007339 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007340 ret = read_sub_module(module, NULL, yin, unres);
7341 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007342 goto error;
7343 }
7344
PavolVican9e81c6a2017-02-09 13:09:07 +01007345 if (ret == 1) {
7346 assert(!unres->count);
7347 } else {
Michal Vasko0f437062018-06-08 15:52:39 +02007348 /* make this module implemented if was not from start */
7349 if (!implement && module->implemented && (unres_schema_add_node(module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1)) {
7350 goto error;
7351 }
7352
PavolVican9e81c6a2017-02-09 13:09:07 +01007353 /* resolve rest of unres items */
7354 if (unres->count && resolve_unres_schema(module, unres)) {
7355 goto error;
7356 }
7357
7358 /* check correctness of includes */
7359 if (lyp_check_include_missing(module)) {
7360 goto error;
7361 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007362 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007363
Radek Krejci95f22ae2017-01-20 14:25:53 +01007364 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007365
7366 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7367 goto error;
7368 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007369
Radek Krejciff4874d2016-03-07 12:30:50 +01007370 if (revision) {
7371 /* check revision of the parsed model */
7372 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007373 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7374 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007375 goto error;
7376 }
7377 }
7378
PavolVican9e81c6a2017-02-09 13:09:07 +01007379 /* add into context if not already there */
7380 if (!ret) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007381 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007382 goto error;
7383 }
Michal Vasko10681e82018-01-16 14:54:16 +01007384
7385 /* remove our submodules from the parsed submodules list */
7386 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007387 } else {
7388 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007389 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007390
7391 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007392 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007393 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007394 }
7395
Michal Vasko44ab1462017-05-18 13:18:36 +02007396 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007397 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007398 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7399 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007400 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007401
7402error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007403 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007404 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007405
7406 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007407 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7408 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007409 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007410 return NULL;
7411 }
7412
Michal Vasko53b7da02018-02-13 15:28:42 +01007413 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007414
Radek Krejci9e757e02017-03-08 17:18:09 +01007415 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007416 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007417 lyp_del_includedup(module, 1);
7418 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007419 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007420}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007421
Radek Krejci37f9ba32017-02-10 16:50:35 +01007422/* logs directly */
7423struct lys_module *
7424yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7425{
7426 struct lyxml_elem *yin;
7427 struct lys_module *result;
7428
Radek Krejcie1bacd72017-03-01 13:18:46 +01007429 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007430 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007431 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007432 return NULL;
7433 }
7434
7435 result = yin_read_module_(ctx, yin, revision, implement);
7436
7437 lyxml_free(ctx, yin);
7438
7439 return result;
7440}
7441
Radek Krejcic1885952017-02-07 09:37:51 +01007442static int
7443yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007444 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007445 const char *true_val, const char *false_val, struct unres_schema *unres)
7446{
7447 uint8_t *val;
7448 const char *str;
7449 struct lyext_substmt *info;
7450
7451 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7452 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007453 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007454 return EXIT_FAILURE;
7455 }
7456 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007457 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007458 return EXIT_FAILURE;
7459 }
7460
Radek Krejcidb35f172017-02-27 11:03:01 +01007461 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007462 return EXIT_FAILURE;
7463 }
7464
7465 str = lyxml_get_attr(node, "value", NULL);
7466 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007467 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007468 } else if (true_val && !strcmp(true_val, str)) {
7469 /* true value */
7470 *val = 1;
7471 } else if (false_val && !strcmp(false_val, str)) {
7472 /* false value */
7473 *val = 2;
7474 } else {
7475 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007476 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007477 return EXIT_FAILURE;
7478 }
7479
7480 return EXIT_SUCCESS;
7481}
7482
Radek Krejci8d6b7422017-02-03 14:42:13 +01007483/*
7484 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7485 * argname - name of the element/attribute where the value is stored
7486 */
7487static int
7488yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007489 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007490 int argelem, const char *argname, struct unres_schema *unres)
7491{
7492 int c;
PavolVican99c70722017-02-18 17:25:52 +01007493 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007494 void *reallocated;
7495 struct lyext_substmt *info;
7496
7497 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7498 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007499 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007500 return EXIT_FAILURE;
7501 }
7502 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007503 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007504 return EXIT_FAILURE;
7505 }
7506
7507 c = 0;
7508 if (info->cardinality >= LY_STMT_CARD_SOME) {
7509 /* there can be multiple instances, str is actually const char *** */
7510 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007511 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007512 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007513 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007514 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007515 if (stmt == LY_STMT_BELONGSTO) {
7516 /* allocate another array for the belongs-to's prefixes */
7517 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007518 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007519 } else if (stmt == LY_STMT_ARGUMENT) {
7520 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007521 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007522 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007523 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007524 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007525 /* get the index in the array to add new item */
7526 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007527 }
Radek Krejci56c80412017-02-09 10:44:16 +01007528 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007529 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007530 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007531 return EXIT_FAILURE;
7532 }
7533
7534 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007535 str[c] = read_yin_subnode(mod->ctx, node, argname);
7536 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007537 return EXIT_FAILURE;
7538 }
Radek Krejci56c80412017-02-09 10:44:16 +01007539 } else {
7540 str[c] = lyxml_get_attr(node, argname, NULL);
7541 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007542 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007543 return EXIT_FAILURE;
7544 } else {
7545 str[c] = lydict_insert(mod->ctx, str[c], 0);
7546 }
7547
7548 if (stmt == LY_STMT_BELONGSTO) {
7549 /* get the belongs-to's mandatory prefix substatement */
7550 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007551 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007552 return EXIT_FAILURE;
7553 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007554 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007555 return EXIT_FAILURE;
7556 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007557 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007558 return EXIT_FAILURE;
7559 }
7560 /* and now finally get the value */
7561 if (p) {
7562 str = p[1];
7563 } else {
7564 str++;
7565 }
7566 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7567 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007568 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007569 return EXIT_FAILURE;
7570 }
7571 str[c] = lydict_insert(mod->ctx, str[c], 0);
7572
PavolVican6d400872017-03-01 15:19:18 +01007573 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 +01007574 return EXIT_FAILURE;
7575 }
PavolVican99c70722017-02-18 17:25:52 +01007576 } else if (stmt == LY_STMT_ARGUMENT) {
7577 str = (p) ? p[1] : str + 1;
7578 if (!node->child) {
7579 /* default value of yin element */
7580 ((uint8_t *)str)[c] = 2;
7581 } else {
7582 /* get optional yin-element substatement */
7583 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007584 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007585 return EXIT_FAILURE;
7586 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007587 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007588 return EXIT_FAILURE;
7589 } else {
7590 /* and now finally get the value */
7591 value = lyxml_get_attr(node->child, "value", NULL);
7592 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007593 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007594 return EXIT_FAILURE;
7595 }
7596 if (ly_strequal(value, "true", 0)) {
7597 ((uint8_t *)str)[c] = 1;
7598 } else if (ly_strequal(value, "false", 0)) {
7599 ((uint8_t *)str)[c] = 2;
7600 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007601 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007602 return EXIT_FAILURE;
7603 }
7604
7605 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7606 return EXIT_FAILURE;
7607 }
7608 }
7609 }
Radek Krejci56c80412017-02-09 10:44:16 +01007610 }
7611 }
7612 if (p) {
7613 /* enlarge the array(s) */
7614 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7615 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007616 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007617 lydict_remove(mod->ctx, p[0][c]);
7618 p[0][c] = NULL;
7619 return EXIT_FAILURE;
7620 }
7621 p[0] = reallocated;
7622 p[0][c + 1] = NULL;
7623
7624 if (stmt == LY_STMT_BELONGSTO) {
7625 /* enlarge the second belongs-to's array with prefixes */
7626 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7627 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007628 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007629 lydict_remove(mod->ctx, p[1][c]);
7630 p[1][c] = NULL;
7631 return EXIT_FAILURE;
7632 }
7633 p[1] = reallocated;
7634 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007635 } else if (stmt == LY_STMT_ARGUMENT){
7636 /* enlarge the second argument's array with yin element */
7637 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7638 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007639 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007640 ((uint8_t *)p[1])[c] = 0;
7641 return EXIT_FAILURE;
7642 }
7643 p[1] = reallocated;
7644 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007645 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007646 }
7647
7648 return EXIT_SUCCESS;
7649}
7650
7651static void *
7652yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7653 uint16_t mask)
7654{
7655 void *data;
7656 struct lyext_substmt *info;
7657
7658 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7659 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007660 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007661 return NULL;
7662 }
7663 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007664 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007665 return NULL;
7666 }
7667
7668 return data;
7669}
7670
Radek Krejcic1885952017-02-07 09:37:51 +01007671static int
7672yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007673 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007674 const char *val1_str, const char *val2_str, uint16_t mask,
7675 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7676{
7677 uint16_t *val;
7678 const char *str;
7679
7680 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7681 if (!val) {
7682 return EXIT_FAILURE;
7683 }
7684
7685 str = lyxml_get_attr(node, "value", NULL);
7686 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007687 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007688 } else if (!strcmp(val1_str, str)) {
7689 *val = *val | val1;
7690 } else if (!strcmp(val2_str, str)) {
7691 *val = *val | val2;
7692 } else {
7693 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007694 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007695 return EXIT_FAILURE;
7696 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007697 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007698 return EXIT_FAILURE;
7699 }
7700 return EXIT_SUCCESS;
7701}
7702
Radek Krejcif95b6292017-02-13 15:57:37 +01007703static struct lys_node **
7704yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7705{
7706 struct lyext_substmt *info;
7707 struct lys_node **snode, *siter;
7708
7709 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7710 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007711 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007712 return NULL;
7713 }
7714 if (info->cardinality < LY_STMT_CARD_SOME) {
7715 LY_TREE_FOR(*snode, siter) {
7716 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007717 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007718 return NULL;
7719 }
7720 }
7721 }
7722
7723 return snode;
7724}
7725
Radek Krejci8d6b7422017-02-03 14:42:13 +01007726static void **
7727yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7728{
7729 int c;
7730 void **data, ***p = NULL;
7731 void *reallocated;
7732 struct lyext_substmt *info;
7733
7734 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7735 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007736 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007737 return NULL;
7738 }
7739 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007740 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007741 return NULL;
7742 }
7743
7744 c = 0;
7745 if (info->cardinality >= LY_STMT_CARD_SOME) {
7746 /* there can be multiple instances, so instead of pointer to array,
7747 * we have in data pointer to pointer to array */
7748 p = (void ***)data;
7749 data = *p;
7750 if (!data) {
7751 /* allocate initial array */
7752 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007753 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007754 } else {
7755 for (c = 0; *data; data++, c++);
7756 }
7757 }
7758
7759 if (p) {
7760 /* enlarge the array */
7761 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007762 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007763 *p = reallocated;
7764 data = *p;
7765 data[c + 1] = NULL;
7766 }
7767
7768 return &data[c];
7769}
7770
7771int
7772lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7773 struct unres_schema *unres)
7774{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007775 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007776 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007777 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007778 const char *value, *name;
7779 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007780 struct lyext_substmt *info;
7781 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007782 long long int ll;
7783 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007784 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007785
Radek Krejcia8d111f2017-05-31 13:57:37 +02007786#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7787 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007788 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007789 (**(TYPE **)TO) = (TYPE)FROM;
7790
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007791#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007792 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7793 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007794 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007795 goto error; \
7796 } \
7797 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007798 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007799 goto error; \
7800 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007801 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007802 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7803 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007804 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007805 if (!(*pp)) { \
7806 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007807 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007808 } else { \
7809 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7810 } \
7811 p = &(*(TYPE**)pp)[i]; \
7812 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007813#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007814 if (pp) { \
7815 /* enlarge the array */ \
7816 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007817 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007818 *pp = reallocated; \
7819 (*(TYPE**)pp)[i + 1] = 0; \
7820 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007821#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7822 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7823 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007824 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007825#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7826 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007827 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007828 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007829 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007830 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7831 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7832 goto error; \
7833 } \
7834 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007835
Radek Krejci8d6b7422017-02-03 14:42:13 +01007836 LY_TREE_FOR_SAFE(yin->child, next, node) {
7837 if (!node->ns) {
7838 /* garbage */
7839 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7840 /* we have the extension's argument */
7841 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007842 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007843 goto error;
7844 }
7845 ext->arg_value = node->content;
7846 node->content = NULL;
7847 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7848 /* extension */
7849 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7850 goto error;
7851 }
7852 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007853 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007854 goto error;
7855 }
7856 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007857 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007858 goto error;
7859 }
7860 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007861 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007862 goto error;
7863 }
7864 } else if (!strcmp(node->name, "type")) {
7865 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7866 if (!type) {
7867 goto error;
7868 }
7869 /* allocate type structure */
7870 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007871 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007872
7873 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007874 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007875 (*type)->der = (struct lys_tpdf *)node;
7876 (*type)->parent = (struct lys_tpdf *)ext;
7877
7878 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7879 (*type)->der = NULL;
7880 goto error;
7881 }
7882 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007883 } else if (!strcmp(node->name, "typedef")) {
7884 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7885 if (!pp) {
7886 goto error;
7887 }
7888 /* allocate typedef structure */
7889 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007890 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007891
7892 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7893 goto error;
7894 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007895 } else if (!strcmp(node->name, "if-feature")) {
7896 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7897 if (!pp) {
7898 goto error;
7899 }
7900 /* allocate iffeature structure */
7901 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007902 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007903
7904 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7905 goto error;
7906 }
7907 } else if (!strcmp(node->name, "status")) {
7908 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7909 if (!p) {
7910 goto error;
7911 }
7912
Michal Vasko53b7da02018-02-13 15:28:42 +01007913 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007914 if (!strcmp(value, "current")) {
7915 *(uint16_t*)p |= LYS_STATUS_CURR;
7916 } else if (!strcmp(value, "deprecated")) {
7917 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7918 } else if (!strcmp(value, "obsolete")) {
7919 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7920 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007921 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007922 goto error;
7923 }
7924
7925 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7926 goto error;
7927 }
Radek Krejcic1885952017-02-07 09:37:51 +01007928 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007929 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007930 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007931 goto error;
7932 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007933 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007934 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007935 goto error;
7936 }
7937 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007938 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007939 goto error;
7940 }
Radek Krejcic1885952017-02-07 09:37:51 +01007941 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007942 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007943 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7944 goto error;
7945 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007946 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007947 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007948 goto error;
7949 }
7950 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007951 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007952 goto error;
7953 }
7954 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007955 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007956 goto error;
7957 }
7958 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007959 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007960 goto error;
7961 }
7962 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007963 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007964 goto error;
7965 }
7966 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007967 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007968 goto error;
7969 }
7970 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007971 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007972 goto error;
7973 }
7974 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007975 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007976 goto error;
7977 }
Radek Krejcic1885952017-02-07 09:37:51 +01007978 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007979 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7980 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007981 goto error;
7982 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007983 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007984 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007985 goto error;
7986 }
7987 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007988 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007989 goto error;
7990 }
7991 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007992 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007993 goto error;
7994 }
7995 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007996 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007997 goto error;
7998 }
Radek Krejcic1885952017-02-07 09:37:51 +01007999 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008000 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008001 goto error;
8002 }
8003 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01008004 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01008005 goto error;
8006 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008007 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008008 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008009
Michal Vasko53b7da02018-02-13 15:28:42 +01008010 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008011 v = strtol(value, NULL, 10);
8012
8013 /* range check */
8014 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008015 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008016 goto error;
8017 }
8018
8019 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
8020 goto error;
8021 }
8022
8023 /* store the value */
8024 (*(uint8_t *)p) = (uint8_t)v;
8025
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008026 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008027 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008028 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008029
Michal Vasko53b7da02018-02-13 15:28:42 +01008030 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008031 while (isspace(value[0])) {
8032 value++;
8033 }
8034
8035 if (!strcmp(value, "unbounded")) {
8036 u = 0;
8037 } else {
8038 /* convert it to uint32_t */
8039 errno = 0; endptr = NULL;
8040 u = strtoul(value, &endptr, 10);
8041 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008042 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008043 goto error;
8044 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008045 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008046
8047 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8048 goto error;
8049 }
8050
8051 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008052 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008053
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008054 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008055 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008056 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008057
Michal Vasko53b7da02018-02-13 15:28:42 +01008058 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008059 while (isspace(value[0])) {
8060 value++;
8061 }
8062
8063 /* convert it to uint32_t */
8064 errno = 0;
8065 endptr = NULL;
8066 u = strtoul(value, &endptr, 10);
8067 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008068 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008069 goto error;
8070 }
8071
8072 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8073 goto error;
8074 }
8075
8076 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008077 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008078
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008079 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008080 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008081 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8082
Michal Vasko53b7da02018-02-13 15:28:42 +01008083 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008084 while (isspace(value[0])) {
8085 value++;
8086 }
8087
8088 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008089 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008090
8091 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008092 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008093 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008094 goto error;
8095 }
8096
8097 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8098 goto error;
8099 }
8100
8101 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008102 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008103
8104 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008105 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008106 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008107
Michal Vasko53b7da02018-02-13 15:28:42 +01008108 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008109 ll = strtoll(value, NULL, 10);
8110
8111 /* range check */
8112 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008113 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008114 goto error;
8115 }
8116
8117 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8118 goto error;
8119 }
8120
8121 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008122 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008123
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008124 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008125 } else if (!strcmp(node->name, "module")) {
8126 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8127 if (!pp) {
8128 goto error;
8129 }
8130
8131 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8132 if (!(*pp)) {
8133 goto error;
8134 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008135 } else if (!strcmp(node->name, "when")) {
8136 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8137
8138 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8139 if (!*(struct lys_when**)p) {
8140 goto error;
8141 }
8142
8143 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008144 } else if (!strcmp(node->name, "revision")) {
8145 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8146
8147 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008148 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008149 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8150 goto error;
8151 }
8152
8153 /* check uniqueness of the revision dates - not required by RFC */
8154 if (pp) {
8155 for (j = 0; j < i; j++) {
8156 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008157 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008158 }
8159 }
8160 }
8161
8162 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008163 } else if (!strcmp(node->name, "unique")) {
8164 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8165
8166 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008167 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008168 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8169 goto error;
8170 }
8171
8172 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8173 goto error;
8174 }
8175 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008176 } else if (!strcmp(node->name, "action")) {
8177 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8178 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008179 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008180 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008181 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008182 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008183 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008184 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008185 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008186 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008187 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008188 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008189 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008190 } else if (!strcmp(node->name, "output")) {
8191 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8192 } else if (!strcmp(node->name, "input")) {
8193 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8194 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008195 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008196 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008197 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008198 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008199 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008200 } else if (!strcmp(node->name, "notification")) {
8201 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8202 } else if (!strcmp(node->name, "uses")) {
8203 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008204 } else if (!strcmp(node->name, "length")) {
8205 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8206 } else if (!strcmp(node->name, "must")) {
8207 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8208 if (!pp) {
8209 goto error;
8210 }
8211 /* allocate structure for must */
8212 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008213 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008214
8215 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8216 goto error;
8217 }
8218 } else if (!strcmp(node->name, "pattern")) {
8219 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008220 GETVAL(mod->ctx, value, node, "value");
8221 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008222 goto error;
8223 }
8224
8225 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008226 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008227
8228 modifier = 0x06; /* ACK */
8229 if (mod->version >= 2) {
8230 name = NULL;
8231 LY_TREE_FOR(node->child, child) {
8232 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8233 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008234 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008235 goto error;
8236 }
8237
Michal Vasko53b7da02018-02-13 15:28:42 +01008238 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008239 if (!strcmp(name, "invert-match")) {
8240 modifier = 0x15; /* NACK */
8241 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008242 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008243 goto error;
8244 }
8245 /* get extensions of the modifier */
8246 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8247 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8248 goto error;
8249 }
8250 }
8251 }
8252 }
8253
8254 /* store the value: modifier byte + value + terminating NULL byte */
8255 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008256 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008257 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8258 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8259 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8260
8261 /* get possible sub-statements */
8262 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8263 goto error;
8264 }
8265
8266 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8267 } else if (!strcmp(node->name, "range")) {
8268 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008269 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008270 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008271 }
8272 lyxml_free(mod->ctx, node);
8273 }
8274
PavolVicanc4b798e2017-02-20 23:15:27 +01008275 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8276 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008277 }
8278
Radek Krejci8d6b7422017-02-03 14:42:13 +01008279 return EXIT_SUCCESS;
8280
8281error:
8282 return EXIT_FAILURE;
8283}