blob: 9b8d952a3c633289c4f688652371ef655806493a [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,
fanchanghufb4152e2021-01-21 20:56:39 +080094 uint8_t *ext_size, struct unres_schema *unres)
Radek Krejci07d0fb92017-01-13 14:11:05 +010095{
96 struct unres_ext *info;
fanchanghufb4152e2021-01-21 20:56:39 +080097 int rc;
Radek Krejci07d0fb92017-01-13 14:11:05 +010098
99 info = malloc(sizeof *info);
Michal Vasko53b7da02018-02-13 15:28:42 +0100100 LY_CHECK_ERR_RETURN(!info, LOGMEM(module->ctx), EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100101 lyxml_unlink(module->ctx, yin);
102 info->data.yin = yin;
103 info->datatype = LYS_IN_YIN;
104 info->parent = parent;
Radek Krejcia7db9702017-01-20 12:55:14 +0100105 info->mod = module;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100106 info->parent_type = parent_type;
107 info->substmt = substmt;
108 info->substmt_index = substmt_index;
fanchanghufb4152e2021-01-21 20:56:39 +0800109 info->ext_index = *ext_size;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100110
fanchanghufb4152e2021-01-21 20:56:39 +0800111 rc = unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info);
112 if (!rc && !(*ext)[*ext_size]) {
113 /* extension instance is skipped */
114 } else {
115 ++(*ext_size);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100116 }
117
fanchanghufb4152e2021-01-21 20:56:39 +0800118 return rc == -1 ? EXIT_FAILURE : EXIT_SUCCESS;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100119}
120
Michal Vasko0d343d12015-08-24 14:57:36 +0200121/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200122static const char *
123read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200124{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200125 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200127 /* there should be <text> child */
128 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100129 LOGERR(ctx, LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
130 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +0100131 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200132 } else if (node->child->content) {
133 len = strlen(node->child->content);
134 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +0100135 } else {
136 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200137 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200138}
139
Radek Krejci8d6b7422017-02-03 14:42:13 +0100140int
141lyp_yin_parse_subnode_ext(struct lys_module *mod, void *elem, LYEXT_PAR elem_type,
Radek Krejciac00b2a2017-01-17 14:05:00 +0100142 struct lyxml_elem *yin, LYEXT_SUBSTMT type, uint8_t i, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +0100143{
Radek Krejci07d0fb92017-01-13 14:11:05 +0100144 void *reallocated;
145 struct lyxml_elem *next, *child;
146 int r;
147 struct lys_ext_instance ***ext;
Michal Vaskoa310a452018-11-21 12:34:29 +0100148 uint8_t *ext_size;
Radek Krejcidce5f972017-09-12 15:47:49 +0200149 const char *statement;
Radek Krejcie534c132016-11-23 13:32:31 +0100150
fanchanghufb4152e2021-01-21 20:56:39 +0800151 r = lyp_get_ext_list(mod->ctx, elem, elem_type, &ext, &ext_size, &statement);
152 LY_CHECK_RETURN(r, EXIT_FAILURE);
Radek Krejcie534c132016-11-23 13:32:31 +0100153
Radek Krejcifccd1442017-01-16 10:26:57 +0100154 if (type == LYEXT_SUBSTMT_SELF) {
155 /* parse for the statement self, not for the substatement */
156 child = yin;
157 next = NULL;
158 goto parseext;
159 }
160
Radek Krejci07d0fb92017-01-13 14:11:05 +0100161 LY_TREE_FOR_SAFE(yin->child, next, child) {
Michal Vaskoc4405722019-03-14 09:17:34 +0100162 if (!child->ns) {
163 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Extension instance \"%s\" is missing namespace.", child->name);
164 return EXIT_FAILURE;
165 }
Radek Krejci07d0fb92017-01-13 14:11:05 +0100166 if (!strcmp(child->ns->value, LY_NSYIN)) {
167 /* skip the regular YIN nodes */
168 continue;
169 }
170
171 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100172parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100173
Michal Vasko53b7da02018-02-13 15:28:42 +0100174 YIN_CHECK_ARRAY_OVERFLOW_RETURN(mod->ctx, *ext_size, *ext_size, "extension", statement, EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100175 /* first, allocate a space for the extension instance in the parent elem */
176 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100177 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100178 (*ext) = reallocated;
179
180 /* init memory */
181 (*ext)[(*ext_size)] = NULL;
182
183 /* parse YIN data */
fanchanghufb4152e2021-01-21 20:56:39 +0800184 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, ext, ext_size, unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100185 if (r) {
186 return EXIT_FAILURE;
187 }
188
fanchanghufb4152e2021-01-21 20:56:39 +0800189 lyp_reduce_ext_list(ext, *ext_size, 1 + (*ext_size));
190
Radek Krejcifccd1442017-01-16 10:26:57 +0100191 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100192 }
193
Radek Krejcie534c132016-11-23 13:32:31 +0100194 return EXIT_SUCCESS;
195}
196
Michal Vasko0d343d12015-08-24 14:57:36 +0200197/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200198static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200199fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
200 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100201{
Radek Krejci5323b492017-01-16 15:40:11 +0100202 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100203 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100204 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100205 struct ly_ctx *ctx = parent->module->ctx;
Michal Vasko1d337e12016-02-15 12:32:04 +0100206
Michal Vasko53b7da02018-02-13 15:28:42 +0100207 GETVAL(ctx, value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200208
209 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100210 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200211error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100212 return EXIT_FAILURE;
213 }
214
Michal Vasko56d082c2016-10-25 14:00:42 +0200215 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100216 return EXIT_FAILURE;
217 }
218
Radek Krejci9de2c042016-10-19 16:53:06 +0200219 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko53b7da02018-02-13 15:28:42 +0100220 lydict_remove(ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200221 if (r) {
222 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100223 }
224
Radek Krejci5323b492017-01-16 15:40:11 +0100225 LY_TREE_FOR_SAFE(yin->child, next, node) {
226 if (!node->ns) {
227 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100228 lyxml_free(ctx, node);
Radek Krejci5323b492017-01-16 15:40:11 +0100229 } else if (strcmp(node->ns->value, LY_NSYIN)) {
230 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100231 YIN_CHECK_ARRAY_OVERFLOW_RETURN(ctx, c_ext, iffeat->ext_size, "extensions", "if-feature", EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100232 c_ext++;
233 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100234 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
Radek Krejci5323b492017-01-16 15:40:11 +0100235 return EXIT_FAILURE;
236 }
237 }
238 if (c_ext) {
239 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100240 LY_CHECK_ERR_RETURN(!iffeat->ext, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100241 LY_TREE_FOR_SAFE(yin->child, next, node) {
242 /* extensions */
243 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
fanchanghufb4152e2021-01-21 20:56:39 +0800244 &iffeat->ext, &iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100245 if (r) {
246 return EXIT_FAILURE;
247 }
248 }
fanchanghufb4152e2021-01-21 20:56:39 +0800249
250 lyp_reduce_ext_list(&iffeat->ext, iffeat->ext_size, c_ext + iffeat->ext_size);
Radek Krejci5323b492017-01-16 15:40:11 +0100251 }
252
Radek Krejci9ff0a922016-07-14 13:08:05 +0200253 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100254}
255
256/* logs directly */
257static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200258fill_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 +0200259{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200260 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +0100261 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200262 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200263 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100264 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100265 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200266
Michal Vasko53b7da02018-02-13 15:28:42 +0100267 GETVAL(ctx, value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100268 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200269
Radek Krejci07d0fb92017-01-13 14:11:05 +0100270 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100271 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200272 }
Radek Krejci04581c62015-05-22 21:24:00 +0200273
Pavol Vicand6cda452016-07-13 15:08:29 +0200274 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100275 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200276 }
277
Radek Krejcie534c132016-11-23 13:32:31 +0100278 LY_TREE_FOR(yin->child, node) {
279 if (strcmp(node->ns->value, LY_NSYIN)) {
280 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +0100281 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ident->ext_size, "extensions", "identity", error);
Radek Krejcie534c132016-11-23 13:32:31 +0100282 c_ext++;
283 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200284 if (c_base && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100285 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100286 goto error;
287 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100288 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_base, ident->base_size, "bases", "identity", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +0100289 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 +0100290 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200291 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200292 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100293
Radek Krejci018f1f52016-08-03 16:01:20 +0200294 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100295 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, ident->iffeature_size, "if-features", "identity", error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200296 c_ftrs++;
297
298 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100299 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100300 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200301 }
302 }
303
304 if (c_base) {
305 ident->base_size = 0;
306 ident->base = calloc(c_base, sizeof *ident->base);
Michal Vasko53b7da02018-02-13 15:28:42 +0100307 LY_CHECK_ERR_GOTO(!ident->base, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200308 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200309 if (c_ftrs) {
310 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +0100311 LY_CHECK_ERR_GOTO(!ident->iffeature, LOGMEM(ctx), error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200312 }
Radek Krejcie534c132016-11-23 13:32:31 +0100313 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100314 /* some extensions may be already present from the substatements */
315 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100316 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci18a44882017-01-23 13:47:29 +0100317 ident->ext = reallocated;
318
319 /* init memory */
320 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100321 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200322
Radek Krejcie534c132016-11-23 13:32:31 +0100323 LY_TREE_FOR_SAFE(yin->child, next, node) {
324 if (strcmp(node->ns->value, LY_NSYIN)) {
325 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +0800326 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 +0100327 if (rc) {
328 goto error;
329 }
330 } else if (!strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100331 GETVAL(ctx, value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100332 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100333 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100334 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200335 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100336
Radek Krejci48464ed2016-03-17 15:44:09 +0100337 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100338 lydict_remove(ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100339 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100340 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100341 lydict_remove(ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200342 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200343 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200344 ident->iffeature_size++;
345 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100346 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200347 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200348 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 }
Radek Krejci04581c62015-05-22 21:24:00 +0200350
fanchanghufb4152e2021-01-21 20:56:39 +0800351 lyp_reduce_ext_list(&ident->ext, ident->ext_size, c_ext + ident->ext_size);
352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200354
355error:
356 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200357}
358
Michal Vasko0d343d12015-08-24 14:57:36 +0200359/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360static int
Radek Krejciaa9c5202017-02-15 16:10:14 +0100361read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
Radek Krejcifccd1442017-01-16 10:26:57 +0100362 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200363{
Radek Krejcifccd1442017-01-16 10:26:57 +0100364 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200365 const char *value;
Michal Vasko53b7da02018-02-13 15:28:42 +0100366 struct ly_ctx *ctx = module->ctx;
Radek Krejci41726f92015-06-19 13:11:05 +0200367
Radek Krejcifccd1442017-01-16 10:26:57 +0100368 LY_TREE_FOR_SAFE(yin->child, next, child) {
369 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200370 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200371 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100372 } else if (strcmp(child->ns->value, LY_NSYIN)) {
373 /* extension */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100374 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100375 return EXIT_FAILURE;
376 }
377 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200378 if (restr->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100379 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200380 return EXIT_FAILURE;
381 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100382 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100383 return EXIT_FAILURE;
384 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100385 restr->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200386 if (!restr->dsc) {
387 return EXIT_FAILURE;
388 }
389 } else if (!strcmp(child->name, "reference")) {
390 if (restr->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100391 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200392 return EXIT_FAILURE;
393 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100394 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100395 return EXIT_FAILURE;
396 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100397 restr->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200398 if (!restr->ref) {
399 return EXIT_FAILURE;
400 }
401 } else if (!strcmp(child->name, "error-app-tag")) {
402 if (restr->eapptag) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100403 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200404 return EXIT_FAILURE;
405 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100406 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100407 return EXIT_FAILURE;
408 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100409 GETVAL(ctx, value, child, "value");
410 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200411 } else if (!strcmp(child->name, "error-message")) {
412 if (restr->emsg) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100413 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200414 return EXIT_FAILURE;
415 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100416 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100417 return EXIT_FAILURE;
418 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100419 restr->emsg = read_yin_subnode(ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200420 if (!restr->emsg) {
421 return EXIT_FAILURE;
422 }
423 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100424 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200425 return EXIT_FAILURE;
426 }
Radek Krejci41726f92015-06-19 13:11:05 +0200427 }
428
429 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200430
431error:
432 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200433}
434
Michal Vasko88c29542015-11-27 14:57:53 +0100435/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
436int
Radek Krejcib8048692015-08-05 13:36:34 +0200437fill_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 +0100438 int parenttype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200439{
Michal Vasko568b1952018-01-30 15:53:30 +0100440 const char *value, *name, *module_name = NULL;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200441 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100442 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100443 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200444 struct lys_type_bit bit, *bits_sc = NULL;
445 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200446 struct lys_type *dertype;
Michal Vasko53b7da02018-02-13 15:28:42 +0100447 struct ly_ctx *ctx = module->ctx;
Radek Krejcidce5f972017-09-12 15:47:49 +0200448 int rc, val_set, c_ftrs, c_ext = 0;
449 unsigned int i, j;
Radek Krejcidc008d72016-02-17 13:12:14 +0100450 int ret = -1;
Michal Vasko0decd2e2020-12-02 10:07:45 +0100451 int64_t v, v_ = 0;
Radek Krejci994b6f62015-06-18 16:47:27 +0200452 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200453 size_t len;
Radek Krejcib53154b2017-07-19 09:14:13 +0200454 int in_grp = 0;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200455 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200456
Radek Krejcie534c132016-11-23 13:32:31 +0100457 /* init */
458 memset(&exts, 0, sizeof exts);
459
Michal Vasko53b7da02018-02-13 15:28:42 +0100460 GETVAL(ctx, value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100461 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200462 if (!value) {
463 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200464 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200465
466 i = parse_identifier(value);
467 if (i < 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100468 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
469 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200470 goto error;
471 }
472 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100473 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200474 if (value[i]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100475 module_name = lydict_insert(ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100476 name += i;
477 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100478 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
479 lydict_remove(ctx, module_name);
480 lydict_remove(ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200481 goto error;
482 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200483 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100484 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200485 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200486
Michal Vasko568b1952018-01-30 15:53:30 +0100487 rc = resolve_superior_type(name, module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200488 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100489 LOGVAL(ctx, LYE_INMOD, LY_VLOG_NONE, NULL, module_name);
490 lydict_remove(ctx, module_name);
491 lydict_remove(ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200492 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100493
494 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200495 } else if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100496 LOGVAL(ctx, LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
497 lydict_remove(ctx, module_name);
498 lydict_remove(ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100499 ret = EXIT_FAILURE;
500 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100502 lydict_remove(ctx, module_name);
503 lydict_remove(ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200504
Michal Vasko101658e2018-06-05 15:05:54 +0200505 if (type->value_flags & LY_VALUE_UNRESGRP) {
Radek Krejcic13db382016-08-16 10:52:42 +0200506 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Michal Vasko70bf8e52018-03-26 11:32:33 +0200507 * unresolved item left inside the grouping, LYTYPE_GRP used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200508 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
509 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200510 assert(((struct lys_node_grp *)siter)->unres_count);
511 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200512 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100513 LOGINT(ctx);
Radek Krejcic13db382016-08-16 10:52:42 +0200514 goto error;
515 }
Michal Vasko101658e2018-06-05 15:05:54 +0200516 type->value_flags &= ~LY_VALUE_UNRESGRP;
Radek Krejcic13db382016-08-16 10:52:42 +0200517 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200518 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200519
Radek Krejcicf509982015-12-15 09:22:44 +0100520 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100521 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Michal Vasko53b7da02018-02-13 15:28:42 +0100522 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100523 return -1;
524 }
525
Radek Krejcie534c132016-11-23 13:32:31 +0100526 /* parse extension instances */
527 LY_TREE_FOR_SAFE(yin->child, next, node) {
528 if (!node->ns) {
529 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +0100530 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100531 continue;
532 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
533 /* YANG (YIN) statements - process later */
534 continue;
535 }
536
Michal Vasko53b7da02018-02-13 15:28:42 +0100537 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, type->ext_size, "extensions", "type", error);
Radek Krejcidce5f972017-09-12 15:47:49 +0200538
Michal Vasko53b7da02018-02-13 15:28:42 +0100539 lyxml_unlink_elem(ctx, node, 2);
540 lyxml_add_child(ctx, &exts, node);
Radek Krejcie534c132016-11-23 13:32:31 +0100541 c_ext++;
542 }
543 if (c_ext) {
544 type->ext = calloc(c_ext, sizeof *type->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +0100545 LY_CHECK_ERR_GOTO(!type->ext, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200546
Radek Krejcie534c132016-11-23 13:32:31 +0100547 LY_TREE_FOR_SAFE(exts.child, next, node) {
fanchanghufb4152e2021-01-21 20:56:39 +0800548 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 +0100549 if (rc) {
550 goto error;
551 }
552 }
fanchanghufb4152e2021-01-21 20:56:39 +0800553
554 lyp_reduce_ext_list(&type->ext, type->ext_size, c_ext + type->ext_size);
Radek Krejcie534c132016-11-23 13:32:31 +0100555 }
556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200558 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200559 /* RFC 6020 9.7.4 - bit */
560
561 /* get bit specifications, at least one must be present */
562 LY_TREE_FOR_SAFE(yin->child, next, node) {
563 if (!strcmp(node->name, "bit")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100564 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.bits.count, type->info.bits.count, "bits", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200565 type->info.bits.count = 0; goto error);
Radek Krejci994b6f62015-06-18 16:47:27 +0200566 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200567 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100568 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200569 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200570 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200571 }
572 }
Radek Krejcie663e012016-08-01 17:12:34 +0200573 dertype = &type->der->type;
574 if (!dertype->der) {
575 if (!type->info.bits.count) {
576 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100577 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200578 goto error;
579 }
580 } else {
581 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
582 if (module->version < 2 && type->info.bits.count) {
583 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
584 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100585 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200586 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200587 goto error;
588 }
Radek Krejciac781922015-07-09 15:35:14 +0200589 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200590
Michal Vaskob930b0b2021-01-04 09:45:24 +0100591 if (type->info.bits.count) {
592 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
593 LY_CHECK_ERR_GOTO(!type->info.bits.bit, LOGMEM(ctx), error);
594 }
Radek Krejcia8d111f2017-05-31 13:57:37 +0200595
Radek Krejci73adb602015-07-02 18:07:40 +0200596 p = 0;
Michal Vaskoc643f712018-09-14 08:26:13 +0200597 i = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200598 LY_TREE_FOR(yin->child, next) {
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200599 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200600
Michal Vasko53b7da02018-02-13 15:28:42 +0100601 GETVAL(ctx, value, next, "name");
602 if (lyp_check_identifier(ctx, value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100603 goto error;
604 }
605
Michal Vasko53b7da02018-02-13 15:28:42 +0100606 type->info.bits.bit[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100607 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 +0200608 type->info.bits.count = i + 1;
609 goto error;
610 }
611
Radek Krejcie663e012016-08-01 17:12:34 +0200612 if (!dertype->der) { /* directly derived type from bits built-in type */
613 /* check the name uniqueness */
614 for (j = 0; j < i; j++) {
615 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100616 LOGVAL(ctx, LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejcie663e012016-08-01 17:12:34 +0200617 type->info.bits.count = i + 1;
618 goto error;
619 }
620 }
621 } else {
622 /* restricted bits type - the name MUST be used in the base type */
623 bits_sc = dertype->info.bits.bit;
624 for (j = 0; j < dertype->info.bits.count; j++) {
625 if (ly_strequal(bits_sc[j].name, value, 1)) {
626 break;
627 }
628 }
629 if (j == dertype->info.bits.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100630 LOGVAL(ctx, LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200631 type->info.bits.count = i + 1;
632 goto error;
633 }
634 }
635
Radek Krejcie663e012016-08-01 17:12:34 +0200636
Radek Krejci0d70c372015-07-02 16:23:10 +0200637 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100638 LY_TREE_FOR_SAFE(next->child, next2, node) {
639 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200640 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200641 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100642 } else if (strcmp(node->ns->value, LY_NSYIN)) {
643 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100644 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Michal Vasko53b7da02018-02-13 15:28:42 +0100645 LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci9b15fea2017-01-23 11:31:43 +0100646 goto error;
647 }
648 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200649 if (p_ != -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100650 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +0200651 type->info.bits.count = i + 1;
652 goto error;
653 }
654
Michal Vasko53b7da02018-02-13 15:28:42 +0100655 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200656 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200657
658 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200659 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100660 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200661 type->info.bits.count = i + 1;
662 goto error;
663 }
664 type->info.bits.bit[i].pos = (uint32_t)p_;
665
Radek Krejcie663e012016-08-01 17:12:34 +0200666 if (!dertype->der) { /* directly derived type from bits built-in type */
667 /* keep the highest enum value for automatic increment */
668 if (type->info.bits.bit[i].pos >= p) {
669 p = type->info.bits.bit[i].pos;
670 p++;
671 } else {
672 /* check that the value is unique */
673 for (j = 0; j < i; j++) {
674 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100675 LOGVAL(ctx, LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +0200676 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
677 type->info.bits.bit[j].name);
678 type->info.bits.count = i + 1;
679 goto error;
680 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200681 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200682 }
683 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200684
Radek Krejci8d6b7422017-02-03 14:42:13 +0100685 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100686 LYEXT_SUBSTMT_POSITION, 0, unres)) {
687 goto error;
688 }
PavolVican92f23622017-12-12 13:35:56 +0100689
PavolVican0144fae2018-02-05 15:54:17 +0100690 for (j = 0; j < type->info.bits.bit[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100691 /* set flag, which represent LYEXT_OPT_VALID */
692 if (type->info.bits.bit[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100693 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100694 break;
695 }
696 }
697
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200698 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100699 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 +0200700 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200701 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100702 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200703 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200704 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200705 }
Radek Krejcie663e012016-08-01 17:12:34 +0200706
707 if (!dertype->der) { /* directly derived type from bits built-in type */
708 if (p_ == -1) {
709 /* assign value automatically */
710 if (p > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100711 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejcie663e012016-08-01 17:12:34 +0200712 type->info.bits.count = i + 1;
713 goto error;
714 }
715 type->info.bits.bit[i].pos = (uint32_t)p;
716 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
717 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200718 }
Radek Krejcie663e012016-08-01 17:12:34 +0200719 } else { /* restricted bits type */
720 if (p_ == -1) {
721 /* automatically assign position from base type */
722 type->info.bits.bit[i].pos = bits_sc[j].pos;
723 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
724 } else {
725 /* check that the assigned position corresponds to the original
726 * position of the bit in the base type */
727 if (p_ != bits_sc[j].pos) {
728 /* p_ - assigned position in restricted bits
729 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100730 LOGVAL(ctx, LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200731 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200732 type->info.bits.count = i + 1;
733 goto error;
734 }
735 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200736 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200737
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200738 /* if-features */
739 if (c_ftrs) {
740 bits_sc = &type->info.bits.bit[i];
741 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
742 if (!bits_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100743 LOGMEM(ctx);
Radek Krejci994b6f62015-06-18 16:47:27 +0200744 type->info.bits.count = i + 1;
745 goto error;
746 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200747
748 LY_TREE_FOR(next->child, node) {
749 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200750 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200751 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
752 bits_sc->iffeature_size++;
753 if (rc) {
754 type->info.bits.count = i + 1;
755 goto error;
756 }
757 }
758 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200759 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200760
761 /* keep them ordered by position */
762 j = i;
763 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
764 /* switch them */
765 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
766 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
767 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
768 j--;
769 }
Michal Vaskoc643f712018-09-14 08:26:13 +0200770
771 ++i;
Radek Krejci994b6f62015-06-18 16:47:27 +0200772 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200773 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200775 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200776 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200777 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200778
Radek Krejcif9401c32015-06-26 16:47:36 +0200779 if (!strcmp(node->name, "range")) {
780 if (type->info.dec64.range) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100781 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200782 goto error;
783 }
784
Michal Vasko53b7da02018-02-13 15:28:42 +0100785 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200786 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko53b7da02018-02-13 15:28:42 +0100787 LY_CHECK_ERR_GOTO(!type->info.dec64.range, LOGMEM(ctx), error);
788 type->info.dec64.range->expr = lydict_insert(ctx, value, 0);
Radek Krejcif9401c32015-06-26 16:47:36 +0200789
790 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100791 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200792 goto error;
793 }
PavolVican0144fae2018-02-05 15:54:17 +0100794 for (j = 0; j < type->info.dec64.range->ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +0100795 /* set flag, which represent LYEXT_OPT_VALID */
796 if (type->info.dec64.range->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +0100797 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +0100798 break;
799 }
800 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200801 } else if (!strcmp(node->name, "fraction-digits")) {
802 if (type->info.dec64.dig) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100803 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200804 goto error;
805 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100806 GETVAL(ctx, value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200807 v = strtol(value, NULL, 10);
808
809 /* range check */
810 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100811 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200812 goto error;
813 }
814 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200815 type->info.dec64.div = 10;
816 for (i = 1; i < v; i++) {
817 type->info.dec64.div *= 10;
818 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100819
820 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100821 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100822 goto error;
823 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200824 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100825 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200826 goto error;
827 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200828 }
829
830 /* mandatory sub-statement(s) check */
831 if (!type->info.dec64.dig && !type->der->type.der) {
832 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vasko53b7da02018-02-13 15:28:42 +0100833 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200834 goto error;
835 }
Radek Krejci7511f402015-07-10 09:56:30 +0200836 if (type->info.dec64.dig && type->der->type.der) {
837 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vasko53b7da02018-02-13 15:28:42 +0100838 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200839 goto error;
840 }
Radek Krejci4800f652016-09-08 14:02:52 +0200841
842 /* copy fraction-digits specification from parent type for easier internal use */
843 if (type->der->type.der) {
844 type->info.dec64.dig = type->der->type.info.dec64.dig;
845 type->info.dec64.div = type->der->type.info.dec64.div;
846 }
847
Michal Vasko53b7da02018-02-13 15:28:42 +0100848 if (type->info.dec64.range && lyp_check_length_range(ctx, type->info.dec64.range->expr, type)) {
849 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200850 goto error;
851 }
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_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200855 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200856
Radek Krejci994b6f62015-06-18 16:47:27 +0200857 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200860 if (!strcmp(node->name, "enum")) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100861 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, type->info.enums.count, type->info.enums.count, "enums", "type",
Radek Krejcidce5f972017-09-12 15:47:49 +0200862 type->info.enums.count = 0; goto error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200863 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200864 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100865 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200866 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200867 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 }
869 }
Radek Krejcie663e012016-08-01 17:12:34 +0200870 dertype = &type->der->type;
871 if (!dertype->der) {
872 if (!type->info.enums.count) {
873 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vasko53b7da02018-02-13 15:28:42 +0100874 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejcie663e012016-08-01 17:12:34 +0200875 goto error;
876 }
877 } else {
878 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
879 if (module->version < 2 && type->info.enums.count) {
880 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
881 * 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 +0100882 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200883 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200884 goto error;
885 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200886 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200887
Michal Vaskob930b0b2021-01-04 09:45:24 +0100888 if (type->info.enums.count) {
889 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
890 LY_CHECK_ERR_GOTO(!type->info.enums.enm, LOGMEM(ctx), error);
891 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200892
Radek Krejcie663e012016-08-01 17:12:34 +0200893 v = 0;
Michal Vaskoc643f712018-09-14 08:26:13 +0200894 i = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200895 LY_TREE_FOR(yin->child, next) {
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200896 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200897
Michal Vasko53b7da02018-02-13 15:28:42 +0100898 GETVAL(ctx, value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100899 if (!value[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100900 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
901 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100902 goto error;
903 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100904 type->info.enums.enm[i].name = lydict_insert(ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100905 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 +0200906 type->info.enums.count = i + 1;
907 goto error;
908 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200910 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200911 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200912 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100913 LOGVAL(ctx, LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200914 type->info.enums.count = i + 1;
915 goto error;
916 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200917
Radek Krejcie663e012016-08-01 17:12:34 +0200918 if (!dertype->der) { /* directly derived type from enumeration built-in type */
919 /* check the name uniqueness */
920 for (j = 0; j < i; j++) {
921 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100922 LOGVAL(ctx, LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
Radek Krejcie663e012016-08-01 17:12:34 +0200923 type->info.enums.count = i + 1;
924 goto error;
925 }
926 }
927 } else {
928 /* restricted enumeration type - the name MUST be used in the base type */
929 enms_sc = dertype->info.enums.enm;
930 for (j = 0; j < dertype->info.enums.count; j++) {
931 if (ly_strequal(enms_sc[j].name, value, 1)) {
932 break;
933 }
934 }
935 if (j == dertype->info.enums.count) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100936 LOGVAL(ctx, LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 type->info.enums.count = i + 1;
938 goto error;
939 }
940 }
Radek Krejci04581c62015-05-22 21:24:00 +0200941
Radek Krejcie663e012016-08-01 17:12:34 +0200942 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100943 LY_TREE_FOR_SAFE(next->child, next2, node) {
944 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200945 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200946 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100947 } else if (strcmp(node->ns->value, LY_NSYIN)) {
948 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100949 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100950 LYEXT_SUBSTMT_SELF, 0, unres)) {
951 goto error;
952 }
953 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200954 if (val_set) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100955 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
Radek Krejcie663e012016-08-01 17:12:34 +0200956 type->info.enums.count = i + 1;
957 goto error;
958 }
959
Michal Vasko53b7da02018-02-13 15:28:42 +0100960 GETVAL(ctx, value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200961 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200962
963 /* range check */
964 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100965 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200966 type->info.enums.count = i + 1;
967 goto error;
968 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200969 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200970
Radek Krejcie663e012016-08-01 17:12:34 +0200971 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200972 if (!i) {
973 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200974 v = type->info.enums.enm[i].value;
975 v++;
976 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200977 /* keep the highest enum value for automatic increment */
978 if (type->info.enums.enm[i].value >= v) {
979 v = type->info.enums.enm[i].value;
980 v++;
981 } else {
982 /* check that the value is unique */
983 for (j = 0; j < i; j++) {
984 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100985 LOGVAL(ctx, LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican5de389c2016-08-30 08:55:15 +0200986 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
987 type->info.enums.enm[j].name);
988 type->info.enums.count = i + 1;
989 goto error;
990 }
Radek Krejcie663e012016-08-01 17:12:34 +0200991 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200992 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 }
994 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200995 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200996
Radek Krejci8d6b7422017-02-03 14:42:13 +0100997 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100998 LYEXT_SUBSTMT_VALUE, 0, unres)) {
999 goto error;
1000 }
PavolVican92f23622017-12-12 13:35:56 +01001001
PavolVican0144fae2018-02-05 15:54:17 +01001002 for (j = 0; j < type->info.enums.enm[i].ext_size; ++j) {
PavolVican92f23622017-12-12 13:35:56 +01001003 /* set flag, which represent LYEXT_OPT_VALID */
1004 if (type->info.enums.enm[i].ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001005 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001006 break;
1007 }
1008 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001009 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001010 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 +02001011 c_ftrs++;
1012
Radek Krejci0d70c372015-07-02 16:23:10 +02001013 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001014 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001015 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001016 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001017 }
Radek Krejcie663e012016-08-01 17:12:34 +02001018
1019 if (!dertype->der) { /* directly derived type from enumeration */
1020 if (!val_set) {
1021 /* assign value automatically */
1022 if (v > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001023 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejcie663e012016-08-01 17:12:34 +02001024 type->info.enums.count = i + 1;
1025 goto error;
1026 }
1027 type->info.enums.enm[i].value = v;
1028 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1029 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001030 }
Radek Krejcie663e012016-08-01 17:12:34 +02001031 } else { /* restricted enum type */
1032 if (!val_set) {
1033 /* automatically assign value from base type */
1034 type->info.enums.enm[i].value = enms_sc[j].value;
1035 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1036 } else {
1037 /* check that the assigned value corresponds to the original
1038 * value of the enum in the base type */
1039 if (v_ != enms_sc[j].value) {
1040 /* v_ - assigned value in restricted enum
1041 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001042 LOGVAL(ctx, LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001043 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001044 type->info.enums.count = i + 1;
1045 goto error;
1046 }
1047 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001049
1050 /* if-features */
1051 if (c_ftrs) {
1052 enms_sc = &type->info.enums.enm[i];
1053 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1054 if (!enms_sc->iffeature) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001055 LOGMEM(ctx);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001056 type->info.enums.count = i + 1;
1057 goto error;
1058 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001059
1060 LY_TREE_FOR(next->child, node) {
1061 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001062 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001063 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1064 enms_sc->iffeature_size++;
1065 if (rc) {
1066 type->info.enums.count = i + 1;
1067 goto error;
1068 }
1069 }
1070 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001072
Michal Vaskoc643f712018-09-14 08:26:13 +02001073 ++i;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 }
1075 break;
1076
1077 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001078 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001079
Michal Vaskof2d43962016-09-02 11:10:16 +02001080 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001081 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001082
Michal Vaskoe29c6622015-11-27 15:02:31 +01001083 if (strcmp(node->name, "base")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001084 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001085 goto error;
1086 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001087
Michal Vasko53b7da02018-02-13 15:28:42 +01001088 GETVAL(ctx, value, yin->child, "name");
Michal Vaskof2d43962016-09-02 11:10:16 +02001089 /* store in the JSON format */
1090 value = transform_schema2json(module, value);
1091 if (!value) {
1092 goto error;
1093 }
1094 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Michal Vasko53b7da02018-02-13 15:28:42 +01001095 lydict_remove(ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001096 if (rc == -1) {
1097 goto error;
1098 }
Radek Krejci18a44882017-01-23 13:47:29 +01001099
Radek Krejci8d6b7422017-02-03 14:42:13 +01001100 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001101 goto error;
1102 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001103 }
1104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001105 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001106 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001107 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001108 break;
1109 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001110 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001111 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001112 } else {
1113 if (type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001114 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
Pavol Vicanf0046f42016-09-07 15:11:09 +02001115 goto error;
1116 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001117 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 if (yin->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001119 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 goto error;
1121 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122 break;
1123
1124 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001125 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001126 LY_TREE_FOR(yin->child, node) {
Radek Krejciaf351422015-06-19 14:49:38 +02001127 if (!strcmp(node->name, "require-instance")) {
1128 if (type->info.inst.req) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001129 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001130 goto error;
1131 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001132 GETVAL(ctx, value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001133 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001134 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001135 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001136 type->info.inst.req = -1;
1137 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001138 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001139 goto error;
1140 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001141
1142 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001143 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001144 goto error;
1145 }
Radek Krejciaf351422015-06-19 14:49:38 +02001146 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001147 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001148 goto error;
1149 }
Radek Krejciaf351422015-06-19 14:49:38 +02001150 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001151
Michal Vaskod439b2a2020-05-04 17:45:14 +02001152 if (type->der->type.der && !type->info.inst.req) {
1153 /* inherit require-instance property */
1154 type->info.inst.req = type->der->type.info.inst.req;
1155 }
1156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157 break;
1158
Radek Krejcif2860132015-06-20 12:37:20 +02001159 case LY_TYPE_BINARY:
1160 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001161 case LY_TYPE_INT8:
1162 case LY_TYPE_INT16:
1163 case LY_TYPE_INT32:
1164 case LY_TYPE_INT64:
1165 case LY_TYPE_UINT8:
1166 case LY_TYPE_UINT16:
1167 case LY_TYPE_UINT32:
1168 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001169 /* RFC 6020 9.2.4 - range */
1170
1171 /* length and range are actually the same restriction, so process
1172 * them by this common code, we just need to differ the name and
1173 * structure where the information will be stored
1174 */
1175 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001176 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001177 name = "length";
1178 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001179 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001180 name = "range";
1181 }
1182
Radek Krejci73adb602015-07-02 18:07:40 +02001183 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001184
Radek Krejcif2860132015-06-20 12:37:20 +02001185 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001186 if (*restrs) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001187 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001188 goto error;
1189 }
1190
Michal Vasko53b7da02018-02-13 15:28:42 +01001191 GETVAL(ctx, value, node, "value");
1192 if (lyp_check_length_range(ctx, value, type)) {
1193 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001194 goto error;
1195 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001196 *restrs = calloc(1, sizeof **restrs);
Michal Vasko53b7da02018-02-13 15:28:42 +01001197 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM(ctx), error);
1198 (*restrs)->expr = lydict_insert(ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001199
1200 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001201 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001202 goto error;
1203 }
PavolVican92f23622017-12-12 13:35:56 +01001204
1205 for (j = 0; j < (*restrs)->ext_size; ++j) {
1206 /* set flag, which represent LYEXT_OPT_VALID */
1207 if ((*restrs)->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001208 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001209 break;
1210 }
1211 }
Radek Krejcif2860132015-06-20 12:37:20 +02001212 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001213 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001214 goto error;
1215 }
Radek Krejcif2860132015-06-20 12:37:20 +02001216 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001217 break;
1218
1219 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001220 /* flag resolving for later use */
Michal Vaskoa2049012019-07-18 13:26:29 +02001221 if (!parenttype && lys_ingrouping(parent)) {
1222 /* just a flag - do not resolve */
1223 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001224 }
1225
Radek Krejcidc4c1412015-06-19 15:39:54 +02001226 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001227 LY_TREE_FOR(yin->child, node) {
Michal Vasko7560ac42019-07-01 08:54:59 +02001228 if (!strcmp(node->name, "path") && !type->der->type.der) {
1229 /* keep path for later */
Michal Vaskod439b2a2020-05-04 17:45:14 +02001230 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko7560ac42019-07-01 08:54:59 +02001231 if (type->info.lref.req) {
1232 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1233 goto error;
1234 }
1235 GETVAL(ctx, value, node, "value");
1236 if (!strcmp(value, "true")) {
1237 type->info.lref.req = 1;
1238 } else if (!strcmp(value, "false")) {
1239 type->info.lref.req = -1;
1240 } else {
1241 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1242 goto error;
1243 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001244
Michal Vasko7560ac42019-07-01 08:54:59 +02001245 /* extensions */
1246 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
1247 goto error;
1248 }
1249 } else {
1250 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1251 goto error;
1252 }
1253 }
1254
1255 /* now that require-instance is properly set, try to find and resolve path */
1256 LY_TREE_FOR(yin->child, node) {
Michal Vasko88c29542015-11-27 14:57:53 +01001257 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001258 if (type->info.lref.path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001259 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001260 goto error;
1261 }
1262
Michal Vasko53b7da02018-02-13 15:28:42 +01001263 GETVAL(ctx, value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001264 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001265 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001266 if (!type->info.lref.path) {
1267 goto error;
1268 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001269
1270 /* try to resolve leafref path only when this is instantiated
1271 * leaf, so it is not:
1272 * - typedef's type,
1273 * - in grouping definition,
1274 * - just instantiated in a grouping definition,
1275 * because in those cases the nodes referenced in path might not be present
1276 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001277 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001278 goto error;
1279 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001280
1281 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001282 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001283 goto error;
1284 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001285
Michal Vasko7560ac42019-07-01 08:54:59 +02001286 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001287 }
Radek Krejci73adb602015-07-02 18:07:40 +02001288 }
1289
Radek Krejci742be352016-07-17 12:18:54 +02001290 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001291 if (!type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001292 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci3a5501d2016-07-18 22:03:34 +02001293 goto error;
1294 } else {
1295 /* copy leafref definition into the derived type */
Michal Vasko53b7da02018-02-13 15:28:42 +01001296 type->info.lref.path = lydict_insert(ctx, type->der->type.info.lref.path, 0);
Michal Vaskod439b2a2020-05-04 17:45:14 +02001297 if (!type->info.lref.req) {
1298 type->info.lref.req = type->der->type.info.lref.req;
1299 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001300 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001301 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001302 goto error;
1303 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001304 }
Radek Krejci742be352016-07-17 12:18:54 +02001305 }
1306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001307 break;
1308
1309 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001310 /* RFC 6020 9.4.4 - length */
1311 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001312 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001313 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001314
Radek Krejci3733a802015-06-19 13:43:21 +02001315 if (!strcmp(node->name, "length")) {
1316 if (type->info.str.length) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001317 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001318 goto error;
1319 }
1320
Michal Vasko53b7da02018-02-13 15:28:42 +01001321 GETVAL(ctx, value, node, "value");
1322 if (lyp_check_length_range(ctx, value, type)) {
1323 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001324 goto error;
1325 }
1326 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko53b7da02018-02-13 15:28:42 +01001327 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM(ctx), error);
1328 type->info.str.length->expr = lydict_insert(ctx, value, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001329
Radek Krejci5fbc9162015-06-19 14:11:11 +02001330 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001331 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001332 goto error;
1333 }
PavolVican92f23622017-12-12 13:35:56 +01001334
1335 for (j = 0; j < type->info.str.length->ext_size; ++j) {
1336 /* set flag, which represent LYEXT_OPT_VALID */
1337 if (type->info.str.length->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001338 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001339 break;
1340 }
1341 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001342 lyxml_free(ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001343 } else if (!strcmp(node->name, "pattern")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001344 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.str.pat_count, "patterns", "type", error);
Radek Krejci73adb602015-07-02 18:07:40 +02001345 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001346 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001347 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001348 goto error;
1349 }
1350 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001351 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001352 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001353 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001354 in_grp = 1;
1355 }
Radek Krejci73adb602015-07-02 18:07:40 +02001356 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko53b7da02018-02-13 15:28:42 +01001357 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM(ctx), error);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001358#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001359 if (!in_grp) {
1360 /* do not compile patterns in groupings */
Michal Vasko95ed90b2017-10-31 14:28:07 +01001361 type->info.str.patterns_pcre = calloc(2 * i, sizeof *type->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001362 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM(ctx), error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001363 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001364#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001365 LY_TREE_FOR(yin->child, node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001366 GETVAL(ctx, value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001367
Michal Vasko9c7dee32018-07-09 09:12:59 +02001368 if (in_grp) {
1369 /* in grouping, just check the pattern syntax */
1370 if (!(ctx->models.flags & LY_CTX_TRUSTED) && lyp_check_pattern(ctx, value, NULL)) {
1371 goto error;
Radek Krejcib53154b2017-07-19 09:14:13 +02001372 }
Michal Vasko69068852015-07-13 14:34:31 +02001373 }
Michal Vasko9c7dee32018-07-09 09:12:59 +02001374#ifdef LY_ENABLED_CACHE
1375 else {
1376 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
1377 if (lyp_precompile_pattern(ctx, value,
1378 (pcre **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1379 (pcre_extra **)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1380 goto error;
1381 }
1382 }
1383#endif
Radek Krejcifccd1442017-01-16 10:26:57 +01001384 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001385 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001386
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001387 modifier = 0x06; /* ACK */
1388 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001389 if (module->version >= 2) {
1390 LY_TREE_FOR_SAFE(node->child, next2, child) {
1391 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1392 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001393 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejcifccd1442017-01-16 10:26:57 +01001394 goto error;
1395 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001396
Michal Vasko53b7da02018-02-13 15:28:42 +01001397 GETVAL(ctx, name, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +01001398 if (!strcmp(name, "invert-match")) {
1399 modifier = 0x15; /* NACK */
1400 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001401 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejcifccd1442017-01-16 10:26:57 +01001402 goto error;
1403 }
1404 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001405 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001406 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1407 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001408 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001409
Michal Vasko53b7da02018-02-13 15:28:42 +01001410 lyxml_free(ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001411 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001412 }
1413 }
1414
1415 len = strlen(value);
1416 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Michal Vasko53b7da02018-02-13 15:28:42 +01001417 LY_CHECK_ERR_GOTO(!buf, LOGMEM(ctx), error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001418 buf[0] = modifier;
1419 strcpy(&buf[1], value);
1420
Michal Vasko53b7da02018-02-13 15:28:42 +01001421 restr->expr = lydict_insert_zc(ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001422
1423 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001424 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001425 goto error;
1426 }
PavolVican92f23622017-12-12 13:35:56 +01001427
1428 for (j = 0; j < restr->ext_size; ++j) {
1429 /* set flag, which represent LYEXT_OPT_VALID */
1430 if (restr->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001431 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001432 break;
1433 }
1434 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001435 }
1436 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001437 break;
1438
1439 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001440 /* RFC 6020 7.4 - type */
1441 /* count number of types in union */
1442 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001443 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001444
Radek Krejcie4c366b2015-07-02 10:11:31 +02001445 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001446 if (type->der->type.der) {
1447 /* type can be a substatement only in "union" type, not in derived types */
Michal Vasko53b7da02018-02-13 15:28:42 +01001448 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
Radek Krejci038d5d92016-09-12 15:07:15 +02001449 goto error;
1450 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001451 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, i, type->info.uni.count, "types", "type", error);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001452 i++;
1453 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001454 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001455 goto error;
1456 }
1457 }
1458
Radek Krejci038d5d92016-09-12 15:07:15 +02001459 if (!i && !type->der->type.der) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001460 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001461 goto error;
1462 }
1463
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001464 /* inherit instid presence information */
1465 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1466 type->info.uni.has_ptr_type = 1;
1467 }
1468
Radek Krejcie4c366b2015-07-02 10:11:31 +02001469 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001470 if (i) {
1471 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001472 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM(ctx), error);
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001473 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001474
Radek Krejcie4c366b2015-07-02 10:11:31 +02001475 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001476 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001477 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001478 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001479 if (!rc) {
1480 type->info.uni.count++;
1481
Radek Krejci7de36cf2016-09-12 16:18:50 +02001482 if (module->version < 2) {
1483 /* union's type cannot be empty or leafref */
1484 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001485 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001486 rc = -1;
1487 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001488 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Radek Krejci7de36cf2016-09-12 16:18:50 +02001489 rc = -1;
1490 }
Michal Vasko88c29542015-11-27 14:57:53 +01001491 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001492
1493 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
Michal Vaskob6ab50c2018-03-08 13:46:10 +01001494 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)
1495 || ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_UNION)
1496 && type->info.uni.types[type->info.uni.count - 1].info.uni.has_ptr_type)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001497 type->info.uni.has_ptr_type = 1;
1498 }
Michal Vasko88c29542015-11-27 14:57:53 +01001499 }
1500 if (rc) {
1501 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1502 for (i = 0; i < type->info.uni.count; ++i) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001503 lys_type_free(ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001504 }
1505 free(type->info.uni.types);
1506 type->info.uni.types = NULL;
1507 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001508 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001509 type->der = NULL;
1510 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001511
1512 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001513 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001514 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001515 goto error;
1516 }
Michal Vasko88c29542015-11-27 14:57:53 +01001517 }
1518 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001519
Michal Vasko88c29542015-11-27 14:57:53 +01001520 case LY_TYPE_BOOL:
1521 case LY_TYPE_EMPTY:
1522 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001523 if (yin->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001524 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001525 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001526 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527 break;
1528
1529 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001530 LOGINT(ctx);
Michal Vasko88c29542015-11-27 14:57:53 +01001531 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001532 }
1533
PavolVican92f23622017-12-12 13:35:56 +01001534 for(j = 0; j < type->ext_size; ++j) {
1535 /* set flag, which represent LYEXT_OPT_VALID */
1536 if (type->ext[j]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001537 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001538 break;
1539 }
1540 }
1541
1542 /* if derived type has extension, which need validate data */
1543 dertype = &type->der->type;
1544 while (dertype->der) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001545 if (dertype->parent->flags & LYS_VALID_EXT) {
1546 type->parent->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001547 }
1548 dertype = &dertype->der->type;
1549 }
1550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001551 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001552
1553error:
Michal Vasko53b7da02018-02-13 15:28:42 +01001554 lyxml_free_withsiblings(ctx, exts.child);
Radek Krejcidc008d72016-02-17 13:12:14 +01001555 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001556}
1557
Michal Vasko0d343d12015-08-24 14:57:36 +02001558/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001560fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1561 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001562{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001563 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001564 struct lyxml_elem *node, *next;
Michal Vasko53b7da02018-02-13 15:28:42 +01001565 struct ly_ctx *ctx = module->ctx;
PavolVican92f23622017-12-12 13:35:56 +01001566 int rc, has_type = 0, c_ext = 0, i;
Radek Krejci59a349f2017-01-24 10:14:31 +01001567 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001568
Michal Vasko53b7da02018-02-13 15:28:42 +01001569 GETVAL(ctx, value, yin, "name");
1570 if (lyp_check_identifier(ctx, value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001571 goto error;
1572 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001573 tpdf->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001575 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001576 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001577 goto error;
1578 }
Radek Krejcieac35532015-05-31 19:09:15 +02001579
Michal Vasko88c29542015-11-27 14:57:53 +01001580 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001581 if (strcmp(node->ns->value, LY_NSYIN)) {
1582 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001583 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, tpdf->ext_size, "extensions", "typedef", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001584 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001585 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001586 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001587 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001588 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001589 goto error;
1590 }
Michal Vasko88c29542015-11-27 14:57:53 +01001591 /* HACK for unres */
1592 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001593 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001594 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001595 goto error;
1596 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001597 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001598
Radek Krejci07d0fb92017-01-13 14:11:05 +01001599 /* 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 +01001600 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 } else if (!strcmp(node->name, "default")) {
1602 if (tpdf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001603 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001604 goto error;
1605 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001606 GETVAL(ctx, value, node, "value");
1607 tpdf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001608
Radek Krejci8d6b7422017-02-03 14:42:13 +01001609 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001610 goto error;
1611 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001612 } else if (!strcmp(node->name, "units")) {
1613 if (tpdf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001614 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001615 goto error;
1616 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001617 GETVAL(ctx, value, node, "name");
1618 tpdf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001619
Radek Krejci8d6b7422017-02-03 14:42:13 +01001620 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001621 goto error;
1622 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001624 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 goto error;
1626 }
Radek Krejcie534c132016-11-23 13:32:31 +01001627
Michal Vasko53b7da02018-02-13 15:28:42 +01001628 lyxml_free(ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001632 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001633 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 goto error;
1635 }
Radek Krejcieac35532015-05-31 19:09:15 +02001636
Michal Vasko478c4652016-07-21 12:55:01 +02001637 /* check default value (if not defined, there still could be some restrictions
1638 * that need to be checked against a default value from a derived type) */
Michal Vasko53b7da02018-02-13 15:28:42 +01001639 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Michal Vasko15a43372017-09-25 14:12:42 +02001640 unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001641 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001643
Radek Krejcie534c132016-11-23 13:32:31 +01001644 /* finish extensions parsing */
1645 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001646 /* some extensions may be already present from the substatements */
1647 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001648 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001649 tpdf->ext = reallocated;
1650
1651 /* init memory */
1652 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1653
Radek Krejcie534c132016-11-23 13:32:31 +01001654 LY_TREE_FOR_SAFE(yin->child, next, node) {
fanchanghufb4152e2021-01-21 20:56:39 +08001655 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 +01001656 if (rc) {
1657 goto error;
1658 }
1659 }
fanchanghufb4152e2021-01-21 20:56:39 +08001660
1661 lyp_reduce_ext_list(&tpdf->ext, tpdf->ext_size, c_ext + tpdf->ext_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001662 }
1663
PavolVican92f23622017-12-12 13:35:56 +01001664 for (i = 0; i < tpdf->ext_size; ++i) {
1665 /* set flag, which represent LYEXT_OPT_VALID */
1666 if (tpdf->ext[i]->flags & LYEXT_OPT_VALID) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01001667 tpdf->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01001668 break;
1669 }
1670 }
1671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001673
1674error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001675 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001676}
1677
Radek Krejcia1a6b762016-11-14 09:53:38 +09001678static int
Radek Krejcie534c132016-11-23 13:32:31 +01001679fill_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 +09001680{
Michal Vasko53b7da02018-02-13 15:28:42 +01001681 struct ly_ctx *ctx = module->ctx;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001682 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001683 struct lyxml_elem *child, *node, *next, *next2;
1684 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001685 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001686
Michal Vasko53b7da02018-02-13 15:28:42 +01001687 GETVAL(ctx, value, yin, "name");
Radek Krejcia1a6b762016-11-14 09:53:38 +09001688
Michal Vasko53b7da02018-02-13 15:28:42 +01001689 if (lyp_check_identifier(ctx, value, LY_IDENT_EXTENSION, module, NULL)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001690 goto error;
1691 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001692 ext->name = lydict_insert(ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001693
Radek Krejci07d0fb92017-01-13 14:11:05 +01001694 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001695 goto error;
1696 }
1697
Radek Krejcie534c132016-11-23 13:32:31 +01001698 LY_TREE_FOR_SAFE(yin->child, next, node) {
1699 if (strcmp(node->ns->value, LY_NSYIN)) {
1700 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01001701 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, ext->ext_size, "extensions", "extension", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001702 c_ext++;
1703 } else if (!strcmp(node->name, "argument")) {
1704 /* argument */
Michal Vasko53b7da02018-02-13 15:28:42 +01001705 GETVAL(ctx, value, node, "name");
1706 ext->argument = lydict_insert(ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001707 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001708 goto error;
1709 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001710
Radek Krejcia1a6b762016-11-14 09:53:38 +09001711 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001712 LY_TREE_FOR_SAFE(node->child, next2, child) {
1713 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001714 GETVAL(ctx, value, child, "value");
Radek Krejcie534c132016-11-23 13:32:31 +01001715 if (ly_strequal(value, "true", 0)) {
1716 ext->flags |= LYS_YINELEM;
1717 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001718
Radek Krejci8d6b7422017-02-03 14:42:13 +01001719 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001720 goto error;
1721 }
Radek Krejcie534c132016-11-23 13:32:31 +01001722 } else if (child->ns) {
1723 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001724 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001725 goto error;
1726 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001727 }
1728
Michal Vasko53b7da02018-02-13 15:28:42 +01001729 lyxml_free(ctx, node);
Radek Krejcie534c132016-11-23 13:32:31 +01001730 } else {
1731 /* unexpected YANG statement */
Michal Vasko53b7da02018-02-13 15:28:42 +01001732 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
Radek Krejcie534c132016-11-23 13:32:31 +01001733 goto error;
1734 }
1735 }
1736
1737 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001738 /* some extensions may be already present from the substatements */
1739 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001740 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001741 ext->ext = reallocated;
1742
1743 /* init memory */
1744 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1745
1746 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001747 LY_TREE_FOR_SAFE(yin->child, next, node) {
fanchanghufb4152e2021-01-21 20:56:39 +08001748 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 +01001749 if (rc) {
1750 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001751 }
1752 }
fanchanghufb4152e2021-01-21 20:56:39 +08001753
1754 lyp_reduce_ext_list(&ext->ext, ext->ext_size, c_ext + ext->ext_size);
Radek Krejcia1a6b762016-11-14 09:53:38 +09001755 }
1756
Radek Krejci0a498f82017-01-04 16:24:15 +01001757 /* search for plugin */
1758 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 +09001759
1760 return EXIT_SUCCESS;
1761
1762error:
1763 return EXIT_FAILURE;
1764}
1765
Michal Vasko0d343d12015-08-24 14:57:36 +02001766/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001767static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001768fill_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 +02001769{
Michal Vasko53b7da02018-02-13 15:28:42 +01001770 struct ly_ctx *ctx = module->ctx;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001771 const char *value;
1772 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001773 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001774 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001775
Michal Vasko53b7da02018-02-13 15:28:42 +01001776 GETVAL(ctx, value, yin, "name");
1777 if (lyp_check_identifier(ctx, value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001778 goto error;
1779 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001780 f->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001781 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001782
Radek Krejci07d0fb92017-01-13 14:11:05 +01001783 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001784 goto error;
1785 }
1786
Radek Krejcie534c132016-11-23 13:32:31 +01001787 LY_TREE_FOR(yin->child, child) {
1788 if (strcmp(child->ns->value, LY_NSYIN)) {
1789 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01001790 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, f->ext_size, "extensions", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001791 c_ext++;
1792 } else if (!strcmp(child->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001793 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, f->iffeature_size, "if-feature", "feature", error);
Radek Krejcie534c132016-11-23 13:32:31 +01001794 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001795 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001796 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001797 goto error;
1798 }
1799 }
1800
Radek Krejcie534c132016-11-23 13:32:31 +01001801 if (c_ftrs) {
1802 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01001803 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001804 }
Radek Krejcie534c132016-11-23 13:32:31 +01001805 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001806 /* some extensions may be already present from the substatements */
1807 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001808 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01001809 f->ext = reallocated;
1810
1811 /* init memory */
1812 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001813 }
1814
Radek Krejcie534c132016-11-23 13:32:31 +01001815 LY_TREE_FOR_SAFE(yin->child, next, child) {
1816 if (strcmp(child->ns->value, LY_NSYIN)) {
1817 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08001818 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 +01001819 if (ret) {
1820 goto error;
1821 }
1822 } else { /* if-feature */
1823 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1824 f->iffeature_size++;
1825 if (ret) {
1826 goto error;
1827 }
1828 }
1829 }
1830
fanchanghufb4152e2021-01-21 20:56:39 +08001831 lyp_reduce_ext_list(&f->ext, f->ext_size, c_ext + f->ext_size);
1832
Radek Krejcic79c6b12016-07-26 15:11:49 +02001833 /* check for circular dependencies */
1834 if (f->iffeature_size) {
1835 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1836 goto error;
1837 }
1838 }
1839
Radek Krejci3cf9e222015-06-18 11:37:50 +02001840 return EXIT_SUCCESS;
1841
1842error:
Radek Krejci3cf9e222015-06-18 11:37:50 +02001843 return EXIT_FAILURE;
1844}
1845
Michal Vasko0d343d12015-08-24 14:57:36 +02001846/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001848fill_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 +02001849{
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001850 int ret = EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001851 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001852
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001853 must->expr = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01001854 GETVAL(module->ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001855 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001856 if (!must->expr) {
1857 goto error;
1858 }
Radek Krejci800af702015-06-02 13:46:01 +02001859
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001860 ret = read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001861
Michal Vasko77dc5652016-02-15 12:32:42 +01001862error:
Michal Vaskoc10f4df2019-11-13 08:24:40 +01001863 if (ret) {
1864 lydict_remove(module->ctx, must->expr);
1865 must->expr = NULL;
1866 }
1867 return ret;
Radek Krejci800af702015-06-02 13:46:01 +02001868}
1869
Radek Krejci581ce772015-11-10 17:22:40 +01001870static int
Radek Krejci7417a082017-02-16 11:07:59 +01001871fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1872 struct unres_schema *unres)
1873{
Michal Vasko53b7da02018-02-13 15:28:42 +01001874 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01001875 struct lyxml_elem *next, *child;
1876 const char *value;
1877
Michal Vasko53b7da02018-02-13 15:28:42 +01001878 GETVAL(ctx, value, yin, "date");
1879 if (lyp_check_date(ctx, value)) {
Radek Krejci7417a082017-02-16 11:07:59 +01001880 goto error;
1881 }
1882 memcpy(rev->date, value, LY_REV_SIZE - 1);
1883
1884 LY_TREE_FOR_SAFE(yin->child, next, child) {
1885 if (!child->ns) {
1886 /* garbage */
1887 continue;
1888 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1889 /* possible extension instance */
1890 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1891 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1892 goto error;
1893 }
1894 } else if (!strcmp(child->name, "description")) {
1895 if (rev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001896 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001897 goto error;
1898 }
1899 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1900 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1901 goto error;
1902 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001903 rev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001904 if (!rev->dsc) {
1905 goto error;
1906 }
1907 } else if (!strcmp(child->name, "reference")) {
1908 if (rev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001909 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001910 goto error;
1911 }
1912 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1913 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1914 goto error;
1915 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001916 rev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejci7417a082017-02-16 11:07:59 +01001917 if (!rev->ref) {
1918 goto error;
1919 }
1920 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01001921 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci7417a082017-02-16 11:07:59 +01001922 goto error;
1923 }
1924 }
1925
1926 return EXIT_SUCCESS;
1927
1928error:
1929 return EXIT_FAILURE;
1930}
1931
1932static int
Michal Vasko88c29542015-11-27 14:57:53 +01001933fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1934 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001935{
Michal Vasko53b7da02018-02-13 15:28:42 +01001936 struct ly_ctx *ctx = module->ctx;
Radek Krejci1a9c3612017-04-24 14:49:43 +02001937 int i, j, ret = EXIT_FAILURE;
1938 const char *orig;
Michal Vasko0decd2e2020-12-02 10:07:45 +01001939 char *value, *vaux, *start = NULL, c = 0;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001940 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001941
1942 /* get unique value (list of leafs supposed to be unique */
Michal Vasko53b7da02018-02-13 15:28:42 +01001943 GETVAL(ctx, orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01001944
1945 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02001946 start = value = vaux = strdup(orig);
Michal Vasko53b7da02018-02-13 15:28:42 +01001947 LY_CHECK_ERR_GOTO(!vaux, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01001948 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001949 YIN_CHECK_ARRAY_OVERFLOW_CODE(ctx, unique->expr_size, unique->expr_size, "referenced items", "unique",
Radek Krejcidce5f972017-09-12 15:47:49 +02001950 unique->expr_size = 0; goto error);
Michal Vasko98645db2016-03-07 14:38:49 +01001951 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001952 while (isspace(*vaux)) {
1953 vaux++;
1954 }
1955 }
1956 unique->expr_size++;
1957 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01001958 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM(ctx), error);
Radek Krejci581ce772015-11-10 17:22:40 +01001959
1960 for (i = 0; i < unique->expr_size; i++) {
1961 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02001962 if (vaux) {
1963 c = *vaux;
1964 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01001965 }
1966
1967 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02001968 unique->expr[i] = transform_schema2json(module, value);
1969 if (vaux) {
1970 *vaux = c;
1971 }
Radek Krejci581ce772015-11-10 17:22:40 +01001972
1973 /* check that the expression does not repeat */
1974 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001975 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001976 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1977 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001978 goto error;
1979 }
1980 }
1981
1982 /* try to resolve leaf */
1983 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001984 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01001985 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02001986 unique_info->list = parent;
1987 unique_info->expr = unique->expr[i];
1988 unique_info->trg_type = &unique->trg_type;
1989 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001990 goto error;
1991 }
Radek Krejci581ce772015-11-10 17:22:40 +01001992 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001993 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001994 goto error;
1995 }
1996 }
1997
1998 /* move to next token */
1999 value = vaux;
Michal Vasko53b7da02018-02-13 15:28:42 +01002000 while (value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002001 value++;
2002 }
2003 }
2004
Radek Krejci1a9c3612017-04-24 14:49:43 +02002005 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01002006
2007error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02002008 free(start);
2009 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01002010}
2011
Michal Vasko0d343d12015-08-24 14:57:36 +02002012/* logs directly
2013 *
Radek Krejcieb00f512015-07-01 16:44:58 +02002014 * type: 0 - min, 1 - max
2015 */
2016static int
Radek Krejcia52656e2015-08-05 13:41:50 +02002017deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02002018{
2019 const char *value;
2020 char *endptr;
2021 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02002022 uint32_t *ui32val, *min, *max;
Michal Vasko53b7da02018-02-13 15:28:42 +01002023 struct ly_ctx *ctx = target->module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002024
Michal Vaskof7e57d52016-03-07 11:31:09 +01002025 /* del min/max is forbidden */
2026 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002027 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002028 goto error;
2029 }
2030
Radek Krejcieb00f512015-07-01 16:44:58 +02002031 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02002032 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002033 max = &((struct lys_node_leaflist *)target)->max;
2034 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02002035 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002036 max = &((struct lys_node_list *)target)->max;
2037 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02002038 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002039 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2040 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002041 goto error;
2042 }
2043
Michal Vasko53b7da02018-02-13 15:28:42 +01002044 GETVAL(ctx, value, node, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002045 while (isspace(value[0])) {
2046 value++;
2047 }
2048
Radek Krejci0d7b2472016-02-12 11:11:03 +01002049 if (type && !strcmp(value, "unbounded")) {
2050 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002051 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002052 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002053 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002054 /* convert it to uint32_t */
2055 errno = 0;
2056 endptr = NULL;
2057 val = strtoul(value, &endptr, 10);
2058 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002059 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002060 goto error;
2061 }
2062 if (type) {
2063 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002064 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002065 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002066 } else {
2067 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002068 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002069 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002070 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002071 }
2072
2073 if (d->mod == LY_DEVIATE_ADD) {
2074 /* check that there is no current value */
2075 if (*ui32val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002076 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2077 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002078 goto error;
2079 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002080 } else if (d->mod == LY_DEVIATE_RPL) {
2081 /* unfortunately, there is no way to check reliably that there
2082 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002083 }
2084
Michal Vaskof7e57d52016-03-07 11:31:09 +01002085 /* add (already checked) and replace */
2086 /* set new value specified in deviation */
2087 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002088
Pavol Vican09adcc32016-08-25 10:51:36 +02002089 /* check min-elements is smaller than max-elements */
2090 if (*max && *min > *max) {
2091 if (type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002092 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
2093 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002094 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002095 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
2096 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Pavol Vican09adcc32016-08-25 10:51:36 +02002097 }
2098 goto error;
2099 }
2100
Radek Krejcieb00f512015-07-01 16:44:58 +02002101 return EXIT_SUCCESS;
2102
2103error:
Radek Krejcieb00f512015-07-01 16:44:58 +02002104 return EXIT_FAILURE;
2105}
2106
Michal Vasko0d343d12015-08-24 14:57:36 +02002107/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002108static int
Michal Vasko88c29542015-11-27 14:57:53 +01002109fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2110 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002111{
2112 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002113 struct lyxml_elem *next, *next2, *child, *develem;
fanchanghufb4152e2021-01-21 20:56:39 +08002114 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0, c_ext2;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002115 int f_min = 0, f_max = 0; /* flags */
Michal Vasko0decd2e2020-12-02 10:07:45 +01002116 int i, j, k = 0, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002117 unsigned int u;
Michal Vasko53b7da02018-02-13 15:28:42 +01002118 struct ly_ctx *ctx = module->ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002119 struct lys_deviate *d = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002120 struct lys_node *node, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002121 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002122 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002123 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002124 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002125 struct lys_node_leaflist *llist = NULL;
Michal Vasko5df038e2018-08-02 09:41:26 +02002126 struct lys_node_inout *inout;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002127 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002128 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002129 struct lys_restr **trg_must = NULL;
Michal Vasko49c709c2020-01-30 14:32:22 +01002130 struct unres_schema *tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002131 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002132 void *reallocated;
Andrew Langefeldf9763242018-09-16 22:23:50 -05002133 size_t deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002134
Michal Vasko53b7da02018-02-13 15:28:42 +01002135 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002136 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002137 if (!dev->target_name) {
2138 goto error;
2139 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002140
2141 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002142 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2143 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002144 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002145 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002146 goto error;
2147 }
Michal Vasko50576712017-07-28 12:28:33 +02002148 dev_target = set->set.s[0];
2149 ly_set_free(set);
2150
Radek Krejcic4283442016-04-22 09:19:27 +02002151 if (dev_target->module == lys_main_module(module)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002152 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2153 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002154 goto error;
2155 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002156
2157 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002158 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002159 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002160 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002161 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002162 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2163 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01002164 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, dev->ext_size, "extensions", "deviation", error);
Radek Krejcie534c132016-11-23 13:32:31 +01002165 c_ext++;
2166 continue;
2167 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002168 if (dev->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002169 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002170 goto error;
2171 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002172 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002173 goto error;
2174 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002175 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002176 if (!dev->dsc) {
2177 goto error;
2178 }
2179 } else if (!strcmp(child->name, "reference")) {
2180 if (dev->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002181 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002182 goto error;
2183 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002184 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002185 goto error;
2186 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002187 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002188 if (!dev->ref) {
2189 goto error;
2190 }
2191 } else if (!strcmp(child->name, "deviate")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002192 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, dev->deviate_size, "deviates", "deviation", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002193 c_dev++;
2194
Michal Vasko345da0a2015-12-02 10:35:55 +01002195 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002196 * further processed later
2197 */
2198 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002199
Radek Krejcieb00f512015-07-01 16:44:58 +02002200 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002201 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002202 goto error;
2203 }
2204
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002205 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002206 }
2207
2208 if (c_dev) {
2209 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko53b7da02018-02-13 15:28:42 +01002210 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM(ctx), error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002211 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002212 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
Pavol Vican09adcc32016-08-25 10:51:36 +02002213 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002214 }
Radek Krejcie534c132016-11-23 13:32:31 +01002215 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002216 /* some extensions may be already present from the substatements */
2217 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002218 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002219 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002220
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002221 /* init memory */
2222 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2223 }
Radek Krejcie534c132016-11-23 13:32:31 +01002224
2225 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2226 if (strcmp(develem->ns->value, LY_NSYIN)) {
2227 /* deviation's extension */
fanchanghufb4152e2021-01-21 20:56:39 +08002228 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 +01002229 if (rc) {
2230 goto error;
2231 }
2232 continue;
2233 }
2234
2235 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 /* init */
2237 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002238 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002239 c_must = 0;
2240 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002241 c_dflt = 0;
fanchanghufb4152e2021-01-21 20:56:39 +08002242 c_ext2 = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002243
2244 /* get deviation type */
Michal Vasko53b7da02018-02-13 15:28:42 +01002245 GETVAL(ctx, value, develem, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002246 if (!strcmp(value, "not-supported")) {
2247 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002248 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002249 * not-supported deviation must be the only deviation of the target
2250 */
2251 if (dev->deviate_size || develem->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002252 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2253 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 +02002254 goto error;
2255 }
2256
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002257 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002258 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2259 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2260 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002261 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2262 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002263 goto error;
2264 }
2265 }
2266 }
Radek Krejci5b917642015-07-02 09:03:13 +02002267
Michal Vaskoff006c12016-02-17 11:15:19 +01002268 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002269 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002270 lys_node_unlink(dev_target);
Michal Vasko5df038e2018-08-02 09:41:26 +02002271 if (parent) {
2272 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
2273 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2274 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2275 * path), so we need to remember the augment as an addition */
2276 /* remember uses parent so we can reconnect to it */
2277 dev_target->parent = parent;
2278 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
2279 /* re-create implicit node */
2280 inout = calloc(1, sizeof *inout);
2281 LY_CHECK_ERR_GOTO(!inout, LOGMEM(ctx), error);
2282
2283 inout->nodetype = dev_target->nodetype;
2284 inout->name = lydict_insert(ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
2285 inout->module = dev_target->module;
2286 inout->flags = LYS_IMPLICIT;
2287
2288 /* insert it manually */
2289 assert(parent->child && !parent->child->next
2290 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
2291 parent->child->next = (struct lys_node *)inout;
2292 inout->prev = parent->child;
2293 parent->child->prev = (struct lys_node *)inout;
2294 inout->parent = parent;
2295 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01002296 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002297 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002298
Radek Krejcieb00f512015-07-01 16:44:58 +02002299 } else if (!strcmp(value, "add")) {
2300 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2301 } else if (!strcmp(value, "replace")) {
2302 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2303 } else if (!strcmp(value, "delete")) {
2304 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2305 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002306 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002307 goto error;
2308 }
2309 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002310 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002311
Michal Vaskoff006c12016-02-17 11:15:19 +01002312 /* store a shallow copy of the original node */
2313 if (!dev->orig_node) {
Michal Vasko49c709c2020-01-30 14:32:22 +01002314 tmp_unres = calloc(1, sizeof *tmp_unres);
2315 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, tmp_unres, 1);
2316 /* such a case is not really supported but whatever */
2317 unres_schema_free(dev_target->module, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002318 }
2319
Radek Krejcieb00f512015-07-01 16:44:58 +02002320 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002321 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002322 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002323 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002324 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002325 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002326 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2327 /* extensions */
fanchanghufb4152e2021-01-21 20:56:39 +08002328 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext2, d->ext_size, "extensions", "deviate", error);
2329 c_ext2++;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002330 } else if (d->mod == LY_DEVIATE_NO) {
2331 /* no YIN substatement expected in this case */
Michal Vasko53b7da02018-02-13 15:28:42 +01002332 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002333 goto error;
2334 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002335 if (d->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002336 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002337 goto error;
2338 }
2339
2340 /* for we deviate from RFC 6020 and allow config property even it is/is not
2341 * specified in the target explicitly since config property inherits. So we expect
2342 * that config is specified in every node. But for delete, we check that the value
2343 * is the same as here in deviation
2344 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002345 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002346 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002347 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002348 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002349 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002350 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002351 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002352 goto error;
2353 }
2354
2355 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002356 /* del config is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002357 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002358 goto error;
Michal Vasko9bc467e2020-01-06 10:09:44 +01002359 } else if ((d->mod == LY_DEVIATE_ADD) && (dev_target->flags & LYS_CONFIG_SET)) {
2360 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
2361 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2362 goto error;
2363 } else if ((d->mod == LY_DEVIATE_RPL) && !(dev_target->flags & LYS_CONFIG_SET)) {
2364 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
2365 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2366 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002367 } else { /* add and replace are the same in this case */
2368 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002369 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002370
2371 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002372 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Michal Vasko435d9e22021-05-18 18:01:41 +02002373
2374 /* "config" is explicitely set in the node */
2375 dev_target->flags |= LYS_CONFIG_SET;
2376
2377 /* "config" must be set to either "yes" or "no" */
2378 assert(dev_target->flags ^ LYS_CONFIG_MASK);
2379
2380 /* check and inherit new config to all the children */
2381 if (lyp_deviate_inherit_config_r(dev_target)) {
2382 goto error;
2383 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002384 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002385
Radek Krejci8d6b7422017-02-03 14:42:13 +01002386 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002387 goto error;
2388 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002389 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002390 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 +01002391 goto error;
2392 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002393 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, d->dflt_size, "defaults", "deviate", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002394 c_dflt++;
2395
2396 /* check target node type */
2397 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002398 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2399 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002400 goto error;
2401 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
Michal Vasko53b7da02018-02-13 15:28:42 +01002402 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2403 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002404 goto error;
2405 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002406 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2407 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002408 goto error;
2409 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002410
Radek Krejcid5a5c282016-08-15 15:38:08 +02002411 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2412 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002413
Radek Krejcieb00f512015-07-01 16:44:58 +02002414 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002415 if (d->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002416 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002417 goto error;
2418 }
2419
2420 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002421 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002422 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2423 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002424 goto error;
2425 }
2426
Michal Vasko53b7da02018-02-13 15:28:42 +01002427 GETVAL(ctx, value, child, "value");
Radek Krejcieb00f512015-07-01 16:44:58 +02002428 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002429 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002430 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002431 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002432 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002433 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002434 goto error;
2435 }
2436
2437 if (d->mod == LY_DEVIATE_ADD) {
2438 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002439 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002440 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2441 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002442 goto error;
2443 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002444
Radek Krejci841ec082016-04-05 13:05:17 +02002445 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002446 if (d->flags & LYS_MAND_TRUE) {
2447 if (dev_target->nodetype == LYS_CHOICE) {
2448 if (((struct lys_node_choice *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002449 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2450 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002451 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2452 goto error;
2453 }
2454 } else if (dev_target->nodetype == LYS_LEAF) {
2455 if (((struct lys_node_leaf *)(dev_target))->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002456 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2457 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcie00d2312016-08-12 15:27:49 +02002458 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2459 goto error;
2460 }
2461 }
Radek Krejci841ec082016-04-05 13:05:17 +02002462 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002463
Michal Vasko21be1b32016-03-07 12:31:34 +01002464 dev_target->flags |= d->flags & LYS_MAND_MASK;
2465 } else if (d->mod == LY_DEVIATE_RPL) {
2466 /* check that there was a value before */
2467 if (!(dev_target->flags & LYS_MAND_MASK)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002468 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2469 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002470 goto error;
2471 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002472
Michal Vasko21be1b32016-03-07 12:31:34 +01002473 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002474 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002475 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002476 /* del mandatory is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002477 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002478 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002479 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002480
2481 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2482 for (parent = dev_target->parent;
2483 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2484 parent = parent->parent) {
2485 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2486 /* stop also on presence containers */
2487 break;
2488 }
2489 }
2490 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2491 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2492 if (lyp_check_mandatory_choice(parent)) {
2493 goto error;
2494 }
2495 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002496
Radek Krejci8d6b7422017-02-03 14:42:13 +01002497 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002498 goto error;
2499 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002500 } else if (!strcmp(child->name, "min-elements")) {
2501 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002502 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002503 goto error;
2504 }
2505 f_min = 1;
2506
Michal Vasko60f4b452016-02-12 11:02:55 +01002507 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002508 goto error;
2509 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002510 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002511 goto error;
2512 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002513 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002514 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002515 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002516 goto error;
2517 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002518 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002519
Michal Vasko60f4b452016-02-12 11:02:55 +01002520 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002521 goto error;
2522 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002523 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002524 goto error;
2525 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002526 } else if (!strcmp(child->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002527 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, d->must_size, "musts", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002528 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002529 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002530 continue;
2531 } else if (!strcmp(child->name, "type")) {
2532 if (d->type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002533 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002534 goto error;
2535 }
2536
Michal Vaskof7e57d52016-03-07 11:31:09 +01002537 /* add, del type is forbidden */
2538 if (d->mod == LY_DEVIATE_ADD) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002539 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002540 goto error;
2541 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002542 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002543 goto error;
2544 }
2545
Radek Krejcieb00f512015-07-01 16:44:58 +02002546 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002547 if (dev_target->nodetype == LYS_LEAF) {
2548 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002549 if (((struct lys_node_leaf *)dev_target)->dflt) {
2550 ly_set_add(dflt_check, dev_target, 0);
2551 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002552 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2553 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002554 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2555 ly_set_add(dflt_check, dev_target, 0);
2556 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002557 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002558 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2559 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002560 goto error;
2561 }
2562
Radek Krejcieb00f512015-07-01 16:44:58 +02002563 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002564 lys_type_free(ctx, t, NULL);
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002565 memset(t, 0, sizeof (struct lys_type));
Michal Vasko88c29542015-11-27 14:57:53 +01002566 /* HACK for unres */
2567 t->der = (struct lys_tpdf *)child;
Radek Krejci0ec2cc52017-11-09 16:30:12 +01002568 t->parent = (struct lys_tpdf *)dev_target;
Michal Vasko3767fb22016-07-21 12:10:57 +02002569 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002570 goto error;
2571 }
2572 d->type = t;
2573 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002574 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 +01002575 goto error;
2576 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002577 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, d->unique_size, "uniques", "deviate", error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002578 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002579 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002580 continue;
2581 } else if (!strcmp(child->name, "units")) {
2582 if (d->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002583 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 goto error;
2585 }
2586
2587 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002588 if (dev_target->nodetype == LYS_LEAFLIST) {
2589 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2590 } else if (dev_target->nodetype == LYS_LEAF) {
2591 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002592 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002593 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2594 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002595 goto error;
2596 }
2597
2598 /* get units value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002599 GETVAL(ctx, value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002600 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002601
2602 /* apply to target */
2603 if (d->mod == LY_DEVIATE_ADD) {
2604 /* check that there is no current value */
2605 if (*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002606 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2607 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002608 goto error;
2609 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002610
Michal Vasko21be1b32016-03-07 12:31:34 +01002611 *stritem = lydict_insert(ctx, value, 0);
2612 } else if (d->mod == LY_DEVIATE_RPL) {
2613 /* check that there was a value before */
2614 if (!*stritem) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002615 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2616 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002617 goto error;
2618 }
2619
2620 lydict_remove(ctx, *stritem);
2621 *stritem = lydict_insert(ctx, value, 0);
2622 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002623 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002624 if (!ly_strequal(*stritem, d->units, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002625 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2626 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002627 goto error;
2628 }
2629 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002630 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002631 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002632
2633 /* remove its extensions */
2634 j = -1;
2635 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2636 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2637 --j;
2638 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002639 }
2640
Radek Krejci8d6b7422017-02-03 14:42:13 +01002641 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002642 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002643 }
2644 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01002645 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002646 goto error;
2647 }
2648
Michal Vasko88c29542015-11-27 14:57:53 +01002649 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002650 }
2651
2652 if (c_must) {
2653 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002654 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002655 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002656 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2657 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002658 break;
Radek Krejci76512572015-08-04 09:47:08 +02002659 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002660 trg_must = &((struct lys_node_container *)dev_target)->must;
2661 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002662 break;
Radek Krejci76512572015-08-04 09:47:08 +02002663 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002664 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2665 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002666 break;
Radek Krejci76512572015-08-04 09:47:08 +02002667 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002668 trg_must = &((struct lys_node_list *)dev_target)->must;
2669 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002670 break;
Radek Krejci76512572015-08-04 09:47:08 +02002671 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002672 case LYS_ANYDATA:
2673 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2674 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002675 break;
2676 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002677 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2678 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002679 goto error;
2680 }
2681
Michal Vaskoc04173b2018-03-09 10:43:22 +01002682 dev_target->flags &= ~(LYS_XPCONF_DEP | LYS_XPSTATE_DEP);
Michal Vasko508a50d2016-09-07 14:50:33 +02002683
Radek Krejcieb00f512015-07-01 16:44:58 +02002684 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002685 /* replace must is forbidden */
Michal Vasko53b7da02018-02-13 15:28:42 +01002686 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002687 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002688 } else if (d->mod == LY_DEVIATE_ADD) {
2689 /* reallocate the must array of the target */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002690 struct lys_restr *must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
2691 LY_CHECK_ERR_GOTO(!must, LOGMEM(ctx), error);
2692 *trg_must = must;
2693 d->must = calloc(c_must, sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02002694 d->must_size = c_must;
2695 } else { /* LY_DEVIATE_DEL */
2696 d->must = calloc(c_must, sizeof *d->must);
2697 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002698 LY_CHECK_ERR_GOTO(!d->must, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002699 }
2700 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002701 /* replace unique is forbidden */
2702 if (d->mod == LY_DEVIATE_RPL) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002703 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002704 goto error;
2705 }
2706
Radek Krejcieb00f512015-07-01 16:44:58 +02002707 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002708 if (dev_target->nodetype != LYS_LIST) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002709 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2710 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002711 goto error;
2712 }
2713
Michal Vasko60f4b452016-02-12 11:02:55 +01002714 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002715 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002716 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002717 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002718 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002719 list->unique = d->unique;
2720 d->unique = &list->unique[list->unique_size];
2721 d->unique_size = c_uniq;
2722 } else { /* LY_DEVIATE_DEL */
2723 d->unique = calloc(c_uniq, sizeof *d->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01002724 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002725 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002726 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002727 if (c_dflt) {
2728 if (d->mod == LY_DEVIATE_ADD) {
2729 /* check that there is no current value */
2730 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2731 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002732 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2733 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002734 goto error;
2735 }
2736
2737 /* check collision with mandatory/min-elements */
2738 if ((dev_target->flags & LYS_MAND_TRUE) ||
2739 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
fredganaa227c02019-11-09 11:27:56 +08002740 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
Michal Vasko53b7da02018-02-13 15:28:42 +01002741 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02002742 "Adding the \"default\" statement is forbidden on %s statement.",
2743 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2744 goto error;
2745 }
2746 } else if (d->mod == LY_DEVIATE_RPL) {
2747 /* check that there was a value before */
2748 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2749 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
fredganaa227c02019-11-09 11:27:56 +08002750 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
Michal Vasko53b7da02018-02-13 15:28:42 +01002751 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002752 goto error;
2753 }
2754 }
2755
2756 if (dev_target->nodetype == LYS_LEAFLIST) {
2757 /* reallocate default list in the target */
2758 llist = (struct lys_node_leaflist *)dev_target;
2759 if (d->mod == LY_DEVIATE_ADD) {
2760 /* reallocate (enlarge) the unique array of the target */
2761 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002762 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002763 } else if (d->mod == LY_DEVIATE_RPL) {
2764 /* reallocate (replace) the unique array of the target */
2765 for (i = 0; i < llist->dflt_size; i++) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002766 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002767 }
2768 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2769 llist->dflt_size = 0;
Michal Vasko53b7da02018-02-13 15:28:42 +01002770 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002771 }
2772 }
2773 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01002774 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM(ctx), error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002775 }
fanchanghufb4152e2021-01-21 20:56:39 +08002776 if (c_ext2) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002777 /* some extensions may be already present from the substatements */
fanchanghufb4152e2021-01-21 20:56:39 +08002778 reallocated = realloc(d->ext, (c_ext2 + d->ext_size) * sizeof *d->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01002779 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002780 d->ext = reallocated;
2781
2782 /* init memory */
fanchanghufb4152e2021-01-21 20:56:39 +08002783 memset(&d->ext[d->ext_size], 0, c_ext2 * sizeof *d->ext);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002784 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002785
2786 /* process deviation properties with 0..n cardinality */
Andrew Langefeldf9763242018-09-16 22:23:50 -05002787 deviate_must_index = 0;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002788 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2789 if (strcmp(child->ns->value, LY_NSYIN)) {
2790 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08002791 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, &d->ext_size, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002792 goto error;
2793 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002794 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002795 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002796 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002797 goto error;
2798 }
2799
2800 /* find must to delete, we are ok with just matching conditions */
2801 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002802 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002803 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002804 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002805 /* ... and maintain the array */
2806 (*trg_must_size)--;
2807 if (i != *trg_must_size) {
2808 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2809 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2810 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2811 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2812 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2813 }
2814 if (!(*trg_must_size)) {
2815 free(*trg_must);
2816 *trg_must = NULL;
2817 } else {
2818 (*trg_must)[*trg_must_size].expr = NULL;
2819 (*trg_must)[*trg_must_size].dsc = NULL;
2820 (*trg_must)[*trg_must_size].ref = NULL;
2821 (*trg_must)[*trg_must_size].eapptag = NULL;
2822 (*trg_must)[*trg_must_size].emsg = NULL;
2823 }
2824
2825 i = -1; /* set match flag */
2826 break;
2827 }
2828 }
2829 d->must_size++;
2830 if (i != -1) {
2831 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002832 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002833 d->must[d->must_size - 1].expr, child->name);
Michal Vasko53b7da02018-02-13 15:28:42 +01002834 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002835 goto error;
2836 }
2837 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002838 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002839 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002840 goto error;
2841 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05002842 memcpy(d->must + deviate_must_index, &((*trg_must)[*trg_must_size]), sizeof *d->must);
2843 ++deviate_must_index;
Radek Krejcieb00f512015-07-01 16:44:58 +02002844 (*trg_must_size)++;
2845 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002846
2847 /* check XPath dependencies again */
Michal Vasko15a43372017-09-25 14:12:42 +02002848 if (*trg_must_size && !(ctx->models.flags & LY_CTX_TRUSTED) &&
2849 (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002850 goto error;
2851 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002852 } else if (!strcmp(child->name, "unique")) {
2853 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002854 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002855 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002856 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002857 goto error;
2858 }
2859
2860 /* find unique structures to delete */
2861 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002862 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002863 continue;
2864 }
2865
Radek Krejci581ce772015-11-10 17:22:40 +01002866 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002867 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002868 break;
2869 }
2870 }
2871
Radek Krejci581ce772015-11-10 17:22:40 +01002872 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002873 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002874 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002875 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002876 }
2877 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002878 /* ... and maintain the array */
2879 list->unique_size--;
2880 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002881 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2882 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002883 }
2884
2885 if (!list->unique_size) {
2886 free(list->unique);
2887 list->unique = NULL;
2888 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002889 list->unique[list->unique_size].expr_size = 0;
2890 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002891 }
2892
Radek Krejci6bd2c022017-02-01 15:04:49 +01002893 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002894 i = -1; /* set match flag */
2895 break;
2896 }
2897 }
2898
2899 d->unique_size++;
2900 if (i != -1) {
2901 /* no match found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002902 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2903 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002904 goto error;
2905 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002906
2907 /* remove extensions of this unique instance from the target node */
2908 j = -1;
2909 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 +01002910 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002911 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2912 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002913 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002914 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002915 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002916 }
2917 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002918 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002919 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002920 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002921 list->unique_size++;
2922 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002923 goto error;
2924 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002925 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002926 } else if (!strcmp(child->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002927 GETVAL(ctx, value, child, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002928 u = strlen(value);
Michal Vasko53b7da02018-02-13 15:28:42 +01002929 d->dflt[d->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002930
2931 if (dev_target->nodetype == LYS_CHOICE) {
2932 choice = (struct lys_node_choice *)dev_target;
2933 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2934 if (rc || !node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002935 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002936 goto error;
2937 }
2938 if (d->mod == LY_DEVIATE_DEL) {
2939 if (!choice->dflt || (choice->dflt != node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002940 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2941 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002942 goto error;
2943 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002944 choice->dflt = NULL;
2945 /* remove extensions of this default instance from the target node */
2946 j = -1;
2947 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2948 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2949 --j;
2950 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002951 } else { /* add or replace */
2952 choice->dflt = node;
2953 if (!choice->dflt) {
2954 /* default branch not found */
Michal Vasko53b7da02018-02-13 15:28:42 +01002955 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002956 goto error;
2957 }
2958 }
2959 } else if (dev_target->nodetype == LYS_LEAF) {
2960 leaf = (struct lys_node_leaf *)dev_target;
2961 if (d->mod == LY_DEVIATE_DEL) {
2962 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002963 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2964 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02002965 goto error;
2966 }
2967 /* remove value */
2968 lydict_remove(ctx, leaf->dflt);
2969 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002970 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002971
2972 /* remove extensions of this default instance from the target node */
2973 j = -1;
2974 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2975 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2976 --j;
2977 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002978 } else { /* add (already checked) and replace */
2979 /* remove value */
2980 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002981 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002982
2983 /* set new value */
2984 leaf->dflt = lydict_insert(ctx, value, u);
2985
Radek Krejcibd117f02016-11-04 16:28:08 +01002986 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002987 ly_set_add(dflt_check, dev_target, 0);
2988 }
2989 } else { /* LYS_LEAFLIST */
2990 llist = (struct lys_node_leaflist *)dev_target;
2991 if (d->mod == LY_DEVIATE_DEL) {
2992 /* find and remove the value in target list */
2993 for (i = 0; i < llist->dflt_size; i++) {
2994 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2995 /* match, remove the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01002996 lydict_remove(ctx, llist->dflt[i]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002997 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002998
2999 /* remove extensions of this default instance from the target node */
3000 j = -1;
3001 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 +01003002 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003003 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
3004 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01003005 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01003006 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01003007 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01003008 }
3009 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003010 break;
3011 }
3012 }
3013 if (i == llist->dflt_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003014 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3015 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003016 goto error;
3017 }
3018 } else {
3019 /* add or replace, anyway we place items into the deviate's list
3020 which propagates to the target */
3021 /* we just want to check that the value isn't already in the list */
3022 for (i = 0; i < llist->dflt_size; i++) {
3023 if (ly_strequal(llist->dflt[i], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003024 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3025 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003026 goto error;
3027 }
3028 }
3029 /* store it in target node */
Michal Vasko53b7da02018-02-13 15:28:42 +01003030 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
Radek Krejcid5a5c282016-08-15 15:38:08 +02003031
3032 /* remember to check it later (it may not fit now, but the type can be deviated too) */
3033 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01003034 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003035 }
3036 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003037 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003038 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003039
fanchanghufb4152e2021-01-21 20:56:39 +08003040 lyp_reduce_ext_list(&d->ext, d->ext_size, c_ext2 + d->ext_size);
3041
Radek Krejcid5a5c282016-08-15 15:38:08 +02003042 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
3043 /* consolidate the final list in the target after removing items from it */
3044 llist = (struct lys_node_leaflist *)dev_target;
3045 for (i = j = 0; j < llist->dflt_size; j++) {
3046 llist->dflt[i] = llist->dflt[j];
3047 if (llist->dflt[i]) {
3048 i++;
3049 }
3050 }
3051 llist->dflt_size = i + 1;
3052 }
Radek Krejcieb00f512015-07-01 16:44:58 +02003053 }
3054
fanchanghufb4152e2021-01-21 20:56:39 +08003055 lyp_reduce_ext_list(&dev->ext, dev->ext_size, c_ext + dev->ext_size);
3056
Michal Vasko43a1feb2016-03-07 12:03:02 +01003057 /* now check whether default value, if any, matches the type */
Michal Vasko53b7da02018-02-13 15:28:42 +01003058 if (!(ctx->models.flags & LY_CTX_TRUSTED)) {
Michal Vasko15a43372017-09-25 14:12:42 +02003059 for (u = 0; u < dflt_check->number; ++u) {
3060 value = NULL;
3061 rc = EXIT_SUCCESS;
3062 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3063 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3064 value = leaf->dflt;
3065 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3066 } else { /* LYS_LEAFLIST */
3067 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3068 for (j = 0; j < llist->dflt_size; j++) {
3069 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3070 (struct lys_node *)(&llist->dflt[j]));
3071 if (rc == -1) {
3072 value = llist->dflt[j];
3073 break;
3074 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003075 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003076
Michal Vasko15a43372017-09-25 14:12:42 +02003077 }
3078 if (rc == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003079 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3080 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
Michal Vasko15a43372017-09-25 14:12:42 +02003081 "The default value \"%s\" of the deviated node \"%s\" no longer matches its type.",
3082 dev->target_name);
3083 goto error;
3084 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003085 }
3086 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01003087
Radek Krejci27fe55e2016-09-13 17:13:35 +02003088 /* mark all the affected modules as deviated and implemented */
3089 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3090 mod = lys_node_module(parent);
3091 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02003092 mod->deviated = 1; /* main module */
3093 parent->module->deviated = 1; /* possible submodule */
Michal Vasko0f437062018-06-08 15:52:39 +02003094 if (!mod->implemented) {
3095 mod->implemented = 1;
3096 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
3097 goto error;
3098 }
Radek Krejci2bb5be72017-02-27 13:07:25 +01003099 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003100 }
3101 }
3102
Radek Krejcid5a5c282016-08-15 15:38:08 +02003103 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003104 return EXIT_SUCCESS;
3105
3106error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003107 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003108 return EXIT_FAILURE;
3109}
3110
Michal Vasko0d343d12015-08-24 14:57:36 +02003111/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003112static int
Radek Krejcib8048692015-08-05 13:36:34 +02003113fill_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 +01003114 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003115{
Michal Vasko53b7da02018-02-13 15:28:42 +01003116 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003118 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003119 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003120 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003121 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003122
Michal Vasko591e0b22015-08-13 13:53:43 +02003123 aug->nodetype = LYS_AUGMENT;
Michal Vasko53b7da02018-02-13 15:28:42 +01003124 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003125 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003126 if (!aug->target_name) {
3127 goto error;
3128 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003130
Radek Krejci07d0fb92017-01-13 14:11:05 +01003131 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003132 goto error;
3133 }
3134
Radek Krejcie534c132016-11-23 13:32:31 +01003135 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3136 if (strcmp(sub->ns->value, LY_NSYIN)) {
3137 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003138 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, aug->ext_size, "extensions", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003139 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003140 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003141 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003142 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, aug->iffeature_size, "if-features", "augment", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003143 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003144 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003145 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003146 if (aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003147 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003148 goto error;
3149 }
3150
Radek Krejci5323b492017-01-16 15:40:11 +01003151 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003152 if (!aug->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003153 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003154 goto error;
3155 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003156 lyxml_free(ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003157 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003158
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003159 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003160 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003161 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003162 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003163 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003164 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003165 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003166 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003167 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003168 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003169 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003170 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003171 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003172 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003173 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003174 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003175 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003176 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003177 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003178 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003179 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003180 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003181 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003182 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003183 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003184 goto error;
3185 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003186
Radek Krejci1d82ef62015-08-07 14:44:40 +02003187 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003188 goto error;
3189 }
3190
Radek Krejci1d82ef62015-08-07 14:44:40 +02003191 node = NULL;
Michal Vasko53b7da02018-02-13 15:28:42 +01003192 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003193 }
3194
Radek Krejcie534c132016-11-23 13:32:31 +01003195 if (c_ftrs) {
3196 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003197 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003198 }
Radek Krejcie534c132016-11-23 13:32:31 +01003199 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003200 /* some extensions may be already present from the substatements */
3201 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003202 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci30701b42017-01-23 16:41:38 +01003203 aug->ext = reallocated;
3204
3205 /* init memory */
3206 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003207 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003208
Radek Krejcie534c132016-11-23 13:32:31 +01003209 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3210 if (strcmp(sub->ns->value, LY_NSYIN)) {
3211 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08003212 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 +01003213 if (ret) {
3214 goto error;
3215 }
3216 } else if (!strcmp(sub->name, "if-feature")) {
3217 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003218 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003219 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003220 goto error;
3221 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003222 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003223 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003224 }
3225
fanchanghufb4152e2021-01-21 20:56:39 +08003226 lyp_reduce_ext_list(&aug->ext, aug->ext_size, c_ext + aug->ext_size);
3227
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003228 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003229 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003230 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003231 * when the uses does and cannot be resolved now for sure
3232 * (the grouping was not yet copied into uses).
3233 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003234 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003235 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003236 goto error;
3237 }
Michal Vasko49291b32015-08-06 09:49:41 +02003238 }
Radek Krejci106efc02015-06-10 14:36:27 +02003239
Michal Vasko508a50d2016-09-07 14:50:33 +02003240 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01003241 if (!(ctx->models.flags & LY_CTX_TRUSTED) && aug->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003242 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003243 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003244 goto error;
3245 }
3246 } else {
3247 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3248 goto error;
3249 }
3250 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003251 }
3252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003254
3255error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003257}
3258
Michal Vasko0d343d12015-08-24 14:57:36 +02003259/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003261fill_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 +02003262{
Michal Vasko53b7da02018-02-13 15:28:42 +01003263 struct ly_ctx *ctx = uses->module->ctx;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003264 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 struct lyxml_elem *sub, *next;
3266 const char *value;
3267 char *endptr;
3268 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003269 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 int r;
3271 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003272 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003273
Radek Krejci363bd4a2016-07-29 14:30:20 +02003274 assert(uses);
3275 module = uses->module; /* shorthand */
3276
Michal Vasko53b7da02018-02-13 15:28:42 +01003277 GETVAL(ctx, value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003278 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003279 if (!rfn->target_name) {
3280 goto error;
3281 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003284 if (!sub->ns) {
3285 /* garbage */
3286 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003287 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003288 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, rfn->ext_size, "extensions", "refine", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003289 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003290 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003291
Radek Krejci411b1bf2017-01-23 16:40:05 +01003292 } else if (!strcmp(sub->name, "description")) {
3293 if (rfn->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003294 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003295 goto error;
3296 }
3297
Radek Krejci8d6b7422017-02-03 14:42:13 +01003298 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003299 goto error;
3300 }
3301
Michal Vasko53b7da02018-02-13 15:28:42 +01003302 rfn->dsc = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003303 if (!rfn->dsc) {
3304 goto error;
3305 }
3306 } else if (!strcmp(sub->name, "reference")) {
3307 if (rfn->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003308 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003309 goto error;
3310 }
3311
Radek Krejci8d6b7422017-02-03 14:42:13 +01003312 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003313 goto error;
3314 }
3315
Michal Vasko53b7da02018-02-13 15:28:42 +01003316 rfn->ref = read_yin_subnode(ctx, sub, "text");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003317 if (!rfn->ref) {
3318 goto error;
3319 }
3320 } else if (!strcmp(sub->name, "config")) {
3321 if (rfn->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003322 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003323 goto error;
3324 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003325 GETVAL(ctx, value, sub, "value");
Radek Krejci411b1bf2017-01-23 16:40:05 +01003326 if (!strcmp(value, "false")) {
3327 rfn->flags |= LYS_CONFIG_R;
3328 } else if (!strcmp(value, "true")) {
3329 rfn->flags |= LYS_CONFIG_W;
3330 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003331 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci411b1bf2017-01-23 16:40:05 +01003332 goto error;
3333 }
3334 rfn->flags |= LYS_CONFIG_SET;
3335
Radek Krejci8d6b7422017-02-03 14:42:13 +01003336 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003337 goto error;
3338 }
Radek Krejcie534c132016-11-23 13:32:31 +01003339 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003340 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 /* check possibility of statements combination */
3343 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003344 if (c_dflt) {
3345 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003346 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003347 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003348 goto error;
3349 }
Radek Krejci200bf712016-08-16 17:11:04 +02003350 rfn->target_type &= LYS_LEAFLIST;
3351 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003352 if (module->version < 2) {
3353 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3354 } else {
3355 /* YANG 1.1 */
3356 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3357 }
Radek Krejci200bf712016-08-16 17:11:04 +02003358 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003360 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3361 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 goto error;
3363 }
3364 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003365 if (module->version < 2) {
3366 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3367 } else {
3368 /* YANG 1.1 */
3369 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3370 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003372
Michal Vasko53b7da02018-02-13 15:28:42 +01003373 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, rfn->dflt_size, "defaults", "refine", error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01003374 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 +01003375 goto error;
3376 }
Radek Krejci200bf712016-08-16 17:11:04 +02003377 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003378 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 } else if (!strcmp(sub->name, "mandatory")) {
3380 /* leaf, choice or anyxml */
3381 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003382 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 goto error;
3384 }
3385 /* just checking the flags in leaf is not sufficient, we would allow
3386 * multiple mandatory statements with the "false" value
3387 */
3388 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 /* check possibility of statements combination */
3391 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003392 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003394 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3395 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 goto error;
3397 }
3398 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003399 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003401
Michal Vasko53b7da02018-02-13 15:28:42 +01003402 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003404 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003406 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003408 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 goto error;
3410 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003411 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003412 goto error;
3413 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 } else if (!strcmp(sub->name, "min-elements")) {
3415 /* list or leaf-list */
3416 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003417 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 goto error;
3419 }
3420 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 /* check possibility of statements combination */
3423 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003424 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003426 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3427 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 goto error;
3429 }
3430 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003431 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003433
Michal Vasko53b7da02018-02-13 15:28:42 +01003434 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 while (isspace(value[0])) {
3436 value++;
3437 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 /* convert it to uint32_t */
3440 errno = 0;
3441 endptr = NULL;
3442 val = strtoul(value, &endptr, 10);
3443 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003444 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003445 goto error;
3446 }
3447 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003448 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003449
Radek Krejci8d6b7422017-02-03 14:42:13 +01003450 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003451 goto error;
3452 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 } else if (!strcmp(sub->name, "max-elements")) {
3454 /* list or leaf-list */
3455 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003456 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 goto error;
3458 }
3459 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 /* check possibility of statements combination */
3462 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003463 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003465 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3466 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 goto error;
3468 }
3469 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003470 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003472
Michal Vasko53b7da02018-02-13 15:28:42 +01003473 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 while (isspace(value[0])) {
3475 value++;
3476 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003477
Radek Krejci0d7b2472016-02-12 11:11:03 +01003478 if (!strcmp(value, "unbounded")) {
3479 rfn->mod.list.max = 0;
3480 } else {
3481 /* convert it to uint32_t */
3482 errno = 0;
3483 endptr = NULL;
3484 val = strtoul(value, &endptr, 10);
3485 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003486 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003487 goto error;
3488 }
3489 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003491 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003492
Radek Krejci8d6b7422017-02-03 14:42:13 +01003493 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003494 goto error;
3495 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 } else if (!strcmp(sub->name, "presence")) {
3497 /* container */
3498 if (rfn->mod.presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003499 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 goto error;
3501 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003503 /* check possibility of statements combination */
3504 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003505 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003507 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3508 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 goto error;
3510 }
3511 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003512 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003514
Michal Vasko53b7da02018-02-13 15:28:42 +01003515 GETVAL(ctx, value, sub, "value");
3516 rfn->mod.presence = lydict_insert(ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003517
Radek Krejci8d6b7422017-02-03 14:42:13 +01003518 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003519 goto error;
3520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 } else if (!strcmp(sub->name, "must")) {
fredgan86754f92019-11-01 16:18:21 +08003522 /* leaf leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003523 /* check possibility of statements combination */
3524 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003525 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003527 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3528 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 goto error;
3530 }
3531 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003532 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003534
Michal Vasko53b7da02018-02-13 15:28:42 +01003535 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, rfn->must_size, "musts", "refine", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003537 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003538
Radek Krejci363bd4a2016-07-29 14:30:20 +02003539 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
fredgan86754f92019-11-01 16:18:21 +08003540 /* leaf, leaf-list, list, container, choice, case, anydata or anyxml */
Radek Krejci363bd4a2016-07-29 14:30:20 +02003541 /* check possibility of statements combination */
3542 if (rfn->target_type) {
fredgan86754f92019-11-01 16:18:21 +08003543 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003544 if (!rfn->target_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003545 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3546 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci363bd4a2016-07-29 14:30:20 +02003547 goto error;
3548 }
3549 } else {
fredgan86754f92019-11-01 16:18:21 +08003550 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003551 }
3552
Michal Vasko53b7da02018-02-13 15:28:42 +01003553 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, rfn->iffeature_size, "if-feature", "refine", error);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003554 c_ftrs++;
3555 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003556 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003557 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 goto error;
3559 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003560
Michal Vasko53b7da02018-02-13 15:28:42 +01003561 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 /* process nodes with cardinality of 0..n */
3565 if (c_must) {
3566 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01003567 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003569 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003570 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003571 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 }
Radek Krejci200bf712016-08-16 17:11:04 +02003573 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003574 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003575 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM(ctx), error);
Radek Krejci200bf712016-08-16 17:11:04 +02003576 }
Radek Krejcie534c132016-11-23 13:32:31 +01003577 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003578 /* some extensions may be already present from the substatements */
3579 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003580 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003581 rfn->ext = reallocated;
3582
3583 /* init memory */
3584 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003585 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003586
Radek Krejcie534c132016-11-23 13:32:31 +01003587 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3588 if (strcmp(sub->ns->value, LY_NSYIN)) {
3589 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08003590 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 +01003591 if (r) {
3592 goto error;
3593 }
3594 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003595 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003596 rfn->iffeature_size++;
3597 if (r) {
3598 goto error;
3599 }
Radek Krejci200bf712016-08-16 17:11:04 +02003600 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003601 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003602 rfn->must_size++;
3603 if (r) {
3604 goto error;
3605 }
Radek Krejci200bf712016-08-16 17:11:04 +02003606 } else { /* default */
Michal Vasko53b7da02018-02-13 15:28:42 +01003607 GETVAL(ctx, value, sub, "value");
Radek Krejci200bf712016-08-16 17:11:04 +02003608
3609 /* check for duplicity */
3610 for (r = 0; r < rfn->dflt_size; r++) {
3611 if (ly_strequal(rfn->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003612 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3613 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
Radek Krejci200bf712016-08-16 17:11:04 +02003614 goto error;
3615 }
3616 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003617 rfn->dflt[rfn->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003618 }
3619 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003620
fanchanghufb4152e2021-01-21 20:56:39 +08003621 lyp_reduce_ext_list(&rfn->ext, rfn->ext_size, c_ext + rfn->ext_size);
3622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003624
3625error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003627}
3628
Michal Vasko0d343d12015-08-24 14:57:36 +02003629/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003630static int
Radek Krejcie534c132016-11-23 13:32:31 +01003631fill_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 +02003632{
Michal Vasko53b7da02018-02-13 15:28:42 +01003633 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003634 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003636 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003637 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003638
Radek Krejcie534c132016-11-23 13:32:31 +01003639 /* init */
3640 memset(&exts, 0, sizeof exts);
3641
3642 LY_TREE_FOR_SAFE(yin->child, next, child) {
3643 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003644 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003645 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003646 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3647 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003648 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, imp->ext_size, "extensions", "import", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003649 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003650 lyxml_unlink_elem(ctx, child, 2);
3651 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003652 } else if (!strcmp(child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003653 GETVAL(ctx, value, child, "value");
3654 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 goto error;
3656 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003657 imp->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003658
Radek Krejci8d6b7422017-02-03 14:42:13 +01003659 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003660 goto error;
3661 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003662 } else if (!strcmp(child->name, "revision-date")) {
3663 if (imp->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003664 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcid52195b2016-06-22 11:18:49 +02003665 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003667 GETVAL(ctx, value, child, "date");
3668 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 goto error;
3670 }
3671 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003672
Radek Krejci8d6b7422017-02-03 14:42:13 +01003673 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003674 goto error;
3675 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003676 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003677 if (imp->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003678 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003679 goto error;
3680 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003681 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003682 goto error;
3683 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003684 imp->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003685 if (!imp->dsc) {
3686 goto error;
3687 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003688 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003689 if (imp->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003690 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003691 goto error;
3692 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003693 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003694 goto error;
3695 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003696 imp->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003697 if (!imp->ref) {
3698 goto error;
3699 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003701 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 goto error;
3703 }
3704 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 /* check mandatory information */
3707 if (!imp->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003708 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 goto error;
3710 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003711
Radek Krejcie534c132016-11-23 13:32:31 +01003712 /* process extensions */
3713 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003714 /* some extensions may be already present from the substatements */
3715 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003716 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003717 imp->ext = reallocated;
3718
3719 /* init memory */
3720 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3721
Radek Krejcie534c132016-11-23 13:32:31 +01003722 LY_TREE_FOR_SAFE(exts.child, next, child) {
3723 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08003724 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 +01003725 if (r) {
3726 goto error;
3727 }
3728 }
fanchanghufb4152e2021-01-21 20:56:39 +08003729
3730 lyp_reduce_ext_list(&imp->ext, imp->ext_size, c_ext + imp->ext_size);
Radek Krejcie534c132016-11-23 13:32:31 +01003731 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003732
Michal Vasko53b7da02018-02-13 15:28:42 +01003733 GETVAL(ctx, value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003734 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003735
3736error:
Radek Krejcie534c132016-11-23 13:32:31 +01003737 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003738 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01003739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003741}
3742
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003743/* logs directly
3744 * returns:
3745 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003746 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003747 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003749fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3750 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003751{
Michal Vasko53b7da02018-02-13 15:28:42 +01003752 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01003753 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003755 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003756 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003757
Radek Krejcie534c132016-11-23 13:32:31 +01003758 /* init */
3759 memset(&exts, 0, sizeof exts);
3760
3761 LY_TREE_FOR_SAFE(yin->child, next, child) {
3762 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003763 /* garbage */
3764 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003765 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3766 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01003767 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, inc->ext_size, "extensions", "include", error);
Radek Krejcie534c132016-11-23 13:32:31 +01003768 c_ext++;
Michal Vasko53b7da02018-02-13 15:28:42 +01003769 lyxml_unlink_elem(ctx, child, 2);
3770 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01003771 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 if (inc->rev[0]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003773 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 goto error;
3775 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003776 GETVAL(ctx, value, child, "date");
3777 if (lyp_check_date(ctx, value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003778 goto error;
3779 }
3780 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003781
Radek Krejci8d6b7422017-02-03 14:42:13 +01003782 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003783 goto error;
3784 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003785 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003786 if (inc->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003787 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003788 goto error;
3789 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003790 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003791 goto error;
3792 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003793 inc->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003794 if (!inc->dsc) {
3795 goto error;
3796 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003797 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003798 if (inc->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003799 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Michal Vasko8bfe3812016-07-27 13:37:52 +02003800 goto error;
3801 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003802 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003803 goto error;
3804 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003805 inc->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko8bfe3812016-07-27 13:37:52 +02003806 if (!inc->ref) {
3807 goto error;
3808 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003810 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003811 goto error;
3812 }
3813 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003814
Radek Krejcie534c132016-11-23 13:32:31 +01003815 /* process extensions */
3816 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003817 /* some extensions may be already present from the substatements */
3818 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01003819 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003820 inc->ext = reallocated;
3821
3822 /* init memory */
3823 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3824
Radek Krejcie534c132016-11-23 13:32:31 +01003825 LY_TREE_FOR_SAFE(exts.child, next, child) {
3826 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08003827 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 +01003828 if (r) {
3829 goto error;
3830 }
3831 }
fanchanghufb4152e2021-01-21 20:56:39 +08003832
3833 lyp_reduce_ext_list(&inc->ext, inc->ext_size, c_ext + inc->ext_size);
Radek Krejcie534c132016-11-23 13:32:31 +01003834 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003835
Michal Vasko53b7da02018-02-13 15:28:42 +01003836 GETVAL(ctx, value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003837 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003838
3839error:
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003840 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003841}
3842
Michal Vasko0d343d12015-08-24 14:57:36 +02003843/* logs directly
3844 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003845 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003846 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003847 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003848 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003850read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3851 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003852{
Radek Krejcie4dce292017-10-30 11:16:47 +01003853 struct lys_node *node = stmt, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 const char *value;
3855 struct lyxml_elem *sub, *next;
3856 struct ly_ctx *const ctx = module->ctx;
Radek Krejci2cc25322017-09-06 16:32:02 +02003857 char *str;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003860 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 if (opt & OPT_IDENT) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003864 GETVAL(ctx, value, xmlnode, "name");
3865 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003866 goto error;
3867 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003868 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 /* process local parameters */
3872 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003873 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003874 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003875 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003876 continue;
3877 }
3878 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003879 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003880 continue;
3881 }
3882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003883 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003884 if (node->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003885 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 goto error;
3887 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003888
Radek Krejci8d6b7422017-02-03 14:42:13 +01003889 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003890 goto error;
3891 }
3892
Radek Krejci1d82ef62015-08-07 14:44:40 +02003893 node->dsc = read_yin_subnode(ctx, sub, "text");
3894 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003895 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 }
3897 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003898 if (node->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003899 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 goto error;
3901 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003902
Radek Krejci8d6b7422017-02-03 14:42:13 +01003903 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003904 goto error;
3905 }
3906
Radek Krejci1d82ef62015-08-07 14:44:40 +02003907 node->ref = read_yin_subnode(ctx, sub, "text");
3908 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003909 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003910 }
3911 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003912 if (node->flags & LYS_STATUS_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003913 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 goto error;
3915 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003916 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003918 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003920 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003922 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003923 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003924 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003925 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003927
Radek Krejci8d6b7422017-02-03 14:42:13 +01003928 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003929 goto error;
3930 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003931 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3932 if (opt & OPT_CFG_PARSE) {
3933 if (node->flags & LYS_CONFIG_MASK) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003934 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003935 goto error;
3936 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003937 GETVAL(ctx, value, sub, "value");
Michal Vaskoe022a562016-09-27 14:24:15 +02003938 if (!strcmp(value, "false")) {
3939 node->flags |= LYS_CONFIG_R;
3940 } else if (!strcmp(value, "true")) {
3941 node->flags |= LYS_CONFIG_W;
3942 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003943 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Michal Vaskoe022a562016-09-27 14:24:15 +02003944 goto error;
3945 }
3946 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003947
Radek Krejci8d6b7422017-02-03 14:42:13 +01003948 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003949 goto error;
3950 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003953 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003954 continue;
3955 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003956 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003958
Michal Vaskoe022a562016-09-27 14:24:15 +02003959 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003961 if (parent) {
3962 node->flags |= parent->flags & LYS_CONFIG_MASK;
3963 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 }
3967 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003968
Radek Krejci2cc25322017-09-06 16:32:02 +02003969 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
3970 /* status is not inherited by specification, but it not make sense to have
3971 * current in deprecated or deprecated in obsolete, so we print warning
3972 * and fix the schema by inheriting */
3973 if (!(node->flags & (LYS_STATUS_MASK))) {
3974 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01003975 if (stmt_type == LYEXT_PAR_NODE) {
3976 p = node->parent;
3977 node->parent = parent;
Michal Vasko395b0a02018-01-22 09:36:20 +01003978 str = lys_path(node, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01003979 node->parent = p;
3980 } else {
Michal Vasko395b0a02018-01-22 09:36:20 +01003981 str = lys_path(parent, LYS_PATH_FIRST_PREFIX);
Radek Krejcie4dce292017-10-30 11:16:47 +01003982 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003983 LOGWRN(ctx, "Missing status in %s subtree (%s), inheriting.",
3984 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
Radek Krejci2cc25322017-09-06 16:32:02 +02003985 free(str);
3986 node->flags |= parent->flags & LYS_STATUS_MASK;
3987 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
3988 /* invalid combination of statuses */
3989 switch (node->flags & LYS_STATUS_MASK) {
3990 case 0:
3991 case LYS_STATUS_CURR:
Michal Vasko53b7da02018-02-13 15:28:42 +01003992 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "current", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02003993 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
3994 break;
3995 case LYS_STATUS_DEPRC:
Michal Vasko53b7da02018-02-13 15:28:42 +01003996 LOGVAL(ctx, LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", xmlnode->name, "is child of",
Radek Krejci2cc25322017-09-06 16:32:02 +02003997 "obsolete", parent->name);
3998 break;
3999 }
4000 goto error;
4001 }
4002 }
4003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02004005
4006error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004007 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004008}
4009
Michal Vasko0d343d12015-08-24 14:57:36 +02004010/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004011static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01004012read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004013{
Michal Vasko53b7da02018-02-13 15:28:42 +01004014 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004015 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01004016 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004017 const char *value;
4018
4019 retval = calloc(1, sizeof *retval);
Michal Vasko53b7da02018-02-13 15:28:42 +01004020 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004021
Michal Vasko53b7da02018-02-13 15:28:42 +01004022 GETVAL(ctx, value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01004023 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02004024 if (!retval->cond) {
4025 goto error;
4026 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004027
Radek Krejci5323b492017-01-16 15:40:11 +01004028 LY_TREE_FOR_SAFE(yin->child, next, child) {
4029 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004030 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02004031 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01004032 } else if (strcmp(child->ns->value, LY_NSYIN)) {
4033 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004034 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004035 goto error;
4036 }
4037 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004038 if (retval->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004039 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004040 goto error;
4041 }
Radek Krejci5323b492017-01-16 15:40:11 +01004042
Radek Krejci8d6b7422017-02-03 14:42:13 +01004043 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004044 goto error;
4045 }
4046
Michal Vasko53b7da02018-02-13 15:28:42 +01004047 retval->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004048 if (!retval->dsc) {
4049 goto error;
4050 }
4051 } else if (!strcmp(child->name, "reference")) {
4052 if (retval->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004053 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004054 goto error;
4055 }
Radek Krejci5323b492017-01-16 15:40:11 +01004056
Radek Krejci8d6b7422017-02-03 14:42:13 +01004057 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004058 goto error;
4059 }
4060
Michal Vasko53b7da02018-02-13 15:28:42 +01004061 retval->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004062 if (!retval->ref) {
4063 goto error;
4064 }
4065 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004066 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004067 goto error;
4068 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004069 }
4070
4071 return retval;
4072
4073error:
Michal Vasko53b7da02018-02-13 15:28:42 +01004074 lys_when_free(ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004075 return NULL;
4076}
4077
Michal Vasko0d343d12015-08-24 14:57:36 +02004078/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004079static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004080read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004081 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02004082{
Michal Vasko53b7da02018-02-13 15:28:42 +01004083 struct ly_ctx *ctx = module->ctx;
Michal Vasko29fc0182015-08-24 15:02:39 +02004084 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 struct lys_node_case *cs;
4086 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01004087 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004088 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004089
Radek Krejcie867c852015-08-27 09:52:34 +02004090 /* init */
4091 memset(&root, 0, sizeof root);
4092
Radek Krejci1d82ef62015-08-07 14:44:40 +02004093 cs = calloc(1, sizeof *cs);
Michal Vasko53b7da02018-02-13 15:28:42 +01004094 LY_CHECK_ERR_RETURN(!cs, LOGMEM(ctx), NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004095 cs->nodetype = LYS_CASE;
4096 cs->prev = (struct lys_node *)cs;
4097 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004098
Radek Krejci07d0fb92017-01-13 14:11:05 +01004099 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004100 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004101 goto error;
4102 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004103
Michal Vasko3e3228d2017-02-24 14:55:32 +01004104 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004105
Michal Vasko3a0043f2015-08-12 12:11:30 +02004106 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004107 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004108 goto error;
4109 }
4110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004111 /* process choice's specific children */
4112 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004113 if (strcmp(sub->ns->value, LY_NSYIN)) {
4114 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004115 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "case", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004116 c_ext++;
4117 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004118 !strcmp(sub->name, "leaf-list") ||
4119 !strcmp(sub->name, "leaf") ||
4120 !strcmp(sub->name, "list") ||
4121 !strcmp(sub->name, "uses") ||
4122 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004123 !strcmp(sub->name, "anyxml") ||
4124 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004125
Michal Vasko53b7da02018-02-13 15:28:42 +01004126 lyxml_unlink_elem(ctx, sub, 2);
4127 lyxml_add_child(ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004128 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004129 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "case", error);
Michal Vasko29fc0182015-08-24 15:02:39 +02004130 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004131 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004132 if (cs->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004133 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004134 goto error;
4135 }
4136
Radek Krejci5323b492017-01-16 15:40:11 +01004137 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004138 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004139 goto error;
4140 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004141
Michal Vasko53b7da02018-02-13 15:28:42 +01004142 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004143 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004144 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004146 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004147 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004148
Radek Krejci3cf9e222015-06-18 11:37:50 +02004149 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004150 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004151 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004152 }
Radek Krejcie534c132016-11-23 13:32:31 +01004153 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004154 /* some extensions may be already present from the substatements */
4155 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004156 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004157 retval->ext = reallocated;
4158
4159 /* init memory */
4160 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 }
Radek Krejci21c81652017-01-23 10:42:55 +01004162
Radek Krejcie534c132016-11-23 13:32:31 +01004163 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4164 if (strcmp(sub->ns->value, LY_NSYIN)) {
4165 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08004166 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 +01004167 if (ret) {
4168 goto error;
4169 }
4170 } else {
4171 /* if-feature */
4172 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4173 cs->iffeature_size++;
4174 if (ret) {
4175 goto error;
4176 }
4177 }
4178 }
Radek Krejcib388c152015-06-04 17:03:03 +02004179
fanchanghufb4152e2021-01-21 20:56:39 +08004180 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
4181
Michal Vasko29fc0182015-08-24 15:02:39 +02004182 /* last part - process data nodes */
4183 LY_TREE_FOR_SAFE(root.child, next, sub) {
4184 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004185 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004186 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004187 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004188 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004189 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004190 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004191 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004192 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004193 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004194 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004195 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004196 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004197 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004198 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004199 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004200 }
4201 if (!node) {
4202 goto error;
4203 }
4204
Michal Vasko53b7da02018-02-13 15:28:42 +01004205 lyxml_free(ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004206 }
4207
Michal Vasko508a50d2016-09-07 14:50:33 +02004208 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004209 if (!(ctx->models.flags & LY_CTX_TRUSTED) && cs->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004210 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004211 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004212 goto error;
4213 }
4214 } else {
4215 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4216 goto error;
4217 }
4218 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004219 }
4220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004221 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004222
4223error:
Michal Vasko29fc0182015-08-24 15:02:39 +02004224 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004225 lyxml_free(ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004226 }
Michal Vasko5ce30802021-03-08 09:34:04 +01004227 lys_node_free(ctx, retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004229 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004230}
4231
Michal Vasko0d343d12015-08-24 14:57:36 +02004232/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004233static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004234read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004235 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004236{
Radek Krejci629cdef2016-06-06 15:06:36 +02004237 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004238 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004239 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004240 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004241 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004242 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004243 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004245 choice = calloc(1, sizeof *choice);
Michal Vasko53b7da02018-02-13 15:28:42 +01004246 LY_CHECK_ERR_RETURN(!choice, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004247
Radek Krejci76512572015-08-04 09:47:08 +02004248 choice->nodetype = LYS_CHOICE;
4249 choice->prev = (struct lys_node *)choice;
4250 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004251
Radek Krejci07d0fb92017-01-13 14:11:05 +01004252 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004253 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4254 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4255 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004256 goto error;
4257 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004258
Michal Vasko3e3228d2017-02-24 14:55:32 +01004259 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004260
Michal Vasko3a0043f2015-08-12 12:11:30 +02004261 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004262 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004263 goto error;
4264 }
4265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004266 /* process choice's specific children */
4267 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004268 if (strcmp(sub->ns->value, LY_NSYIN)) {
4269 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004270 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "choice", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004271 c_ext++;
4272 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004273 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004274 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004275 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 goto error;
4277 }
4278 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004279 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 goto error;
4281 }
4282 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004283 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004284 goto error;
4285 }
4286 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004287 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004288 goto error;
4289 }
4290 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004291 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004292 goto error;
4293 }
4294 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004295 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004296 goto error;
4297 }
4298 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004299 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004300 goto error;
4301 }
4302 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004303 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004304 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004305 goto error;
4306 }
Radek Krejci21c81652017-01-23 10:42:55 +01004307
Radek Krejci8d6b7422017-02-03 14:42:13 +01004308 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004309 goto error;
4310 }
4311
Radek Krejci629cdef2016-06-06 15:06:36 +02004312 dflt = sub;
4313 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004314 continue;
4315 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 } else if (!strcmp(sub->name, "mandatory")) {
4318 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004319 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004320 goto error;
4321 }
4322 /* just checking the flags in leaf is not sufficient, we would allow
4323 * multiple mandatory statements with the "false" value
4324 */
4325 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004326
Michal Vasko53b7da02018-02-13 15:28:42 +01004327 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004328 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004329 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004330 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004331 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004332 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004333 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 goto error;
4335 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004336
Radek Krejci8d6b7422017-02-03 14:42:13 +01004337 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004338 goto error;
4339 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004340 } else if (!strcmp(sub->name, "when")) {
4341 if (choice->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004342 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004343 goto error;
4344 }
4345
Radek Krejci5323b492017-01-16 15:40:11 +01004346 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004347 if (!choice->when) {
4348 goto error;
4349 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004350 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004351 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "choice", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004352 c_ftrs++;
4353
Michal Vasko345da0a2015-12-02 10:35:55 +01004354 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004355 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004356 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004357 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004358 goto error;
4359 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004361 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004363 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004364
Radek Krejci1d82ef62015-08-07 14:44:40 +02004365 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004366 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004368
Radek Krejci3cf9e222015-06-18 11:37:50 +02004369 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004370 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004371 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004372 }
Radek Krejcie534c132016-11-23 13:32:31 +01004373 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004374 /* some extensions may be already present from the substatements */
4375 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004376 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci21c81652017-01-23 10:42:55 +01004377 retval->ext = reallocated;
4378
4379 /* init memory */
4380 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004381 }
4382
Radek Krejcie534c132016-11-23 13:32:31 +01004383 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4384 if (strcmp(sub->ns->value, LY_NSYIN)) {
4385 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08004386 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 +01004387 if (ret) {
4388 goto error;
4389 }
4390 } else {
4391 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4392 choice->iffeature_size++;
4393 if (ret) {
4394 goto error;
4395 }
4396 }
4397 }
4398
fanchanghufb4152e2021-01-21 20:56:39 +08004399 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
4400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004401 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004402 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004403 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
4404 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 goto error;
4406 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004409 if (dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004410 GETVAL(ctx, value, dflt, "value");
Radek Krejci629cdef2016-06-06 15:06:36 +02004411 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004412 goto error;
4413 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004414 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004416
Michal Vasko508a50d2016-09-07 14:50:33 +02004417 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004418 if (!(ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004419 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004420 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004421 goto error;
4422 }
4423 } else {
4424 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4425 goto error;
4426 }
4427 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004428 }
4429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004430 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004431
4432error:
Radek Krejci629cdef2016-06-06 15:06:36 +02004433 lyxml_free(ctx, dflt);
Michal Vasko5ce30802021-03-08 09:34:04 +01004434 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004436}
4437
Michal Vasko0d343d12015-08-24 14:57:36 +02004438/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004439static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004440read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004441 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004442{
Michal Vasko53b7da02018-02-13 15:28:42 +01004443 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004444 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004445 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 struct lyxml_elem *sub, *next;
4447 const char *value;
4448 int r;
4449 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004450 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004451 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko53b7da02018-02-13 15:28:42 +01004454 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004455
Radek Krejcibf2abff2016-08-23 15:51:52 +02004456 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004457 anyxml->prev = (struct lys_node *)anyxml;
4458 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004459
Radek Krejci07d0fb92017-01-13 14:11:05 +01004460 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004461 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
Michal Vasko53b7da02018-02-13 15:28:42 +01004462 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 goto error;
4464 }
Radek Krejci863c2852015-06-03 15:47:11 +02004465
Michal Vasko3e3228d2017-02-24 14:55:32 +01004466 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004467
Radek Krejcic189a952016-07-11 15:27:07 +02004468 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004469 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004470 goto error;
4471 }
4472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004474 if (strcmp(sub->ns->value, LY_NSYIN)) {
4475 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004476 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "anydata", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004477 c_ext++;
4478 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004480 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 goto error;
4482 }
4483 /* just checking the flags in leaf is not sufficient, we would allow
4484 * multiple mandatory statements with the "false" value
4485 */
4486 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004487
Michal Vasko53b7da02018-02-13 15:28:42 +01004488 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004490 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004491 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004492 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004493 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004494 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 goto error;
4496 }
4497 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004498
Radek Krejci8d6b7422017-02-03 14:42:13 +01004499 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004500 goto error;
4501 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004502 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004503 } else if (!strcmp(sub->name, "when")) {
4504 if (anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004505 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004506 goto error;
4507 }
4508
Radek Krejci5323b492017-01-16 15:40:11 +01004509 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004510 if (!anyxml->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004511 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004512 goto error;
4513 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004514 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004516 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, anyxml->must_size, "musts", "anydata", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004518 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004519 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "anydata", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004520 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004523 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 }
4526 }
Radek Krejci863c2852015-06-03 15:47:11 +02004527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 /* middle part - process nodes with cardinality of 0..n */
4529 if (c_must) {
4530 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004531 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004533 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004534 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004535 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004536 }
Radek Krejcie534c132016-11-23 13:32:31 +01004537 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004538 /* some extensions may be already present from the substatements */
4539 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004540 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004541 retval->ext = reallocated;
4542
4543 /* init memory */
4544 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004545 }
Radek Krejci863c2852015-06-03 15:47:11 +02004546
Radek Krejcie534c132016-11-23 13:32:31 +01004547 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4548 if (strcmp(sub->ns->value, LY_NSYIN)) {
4549 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08004550 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 +01004551 if (r) {
4552 goto error;
4553 }
4554 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004555 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004556 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004557 if (r) {
4558 goto error;
4559 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004560 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004561 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004562 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004563 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004564 goto error;
4565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 }
Radek Krejci863c2852015-06-03 15:47:11 +02004568
fanchanghufb4152e2021-01-21 20:56:39 +08004569 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
4570
Michal Vasko508a50d2016-09-07 14:50:33 +02004571 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004572 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (anyxml->when || anyxml->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004573 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004574 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004575 goto error;
4576 }
4577 } else {
4578 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4579 goto error;
4580 }
4581 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004582 }
4583
PavolVican92f23622017-12-12 13:35:56 +01004584 for (r = 0; r < retval->ext_size; ++r) {
4585 /* set flag, which represent LYEXT_OPT_VALID */
Michal Vaskoa3917d92021-03-08 14:08:05 +01004586 if (retval->ext[r] && (retval->ext[r]->flags & LYEXT_OPT_VALID)) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004587 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004588 break;
4589 }
4590 }
4591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004593
4594error:
Michal Vasko5ce30802021-03-08 09:34:04 +01004595 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004597}
4598
Michal Vasko0d343d12015-08-24 14:57:36 +02004599/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004600static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004601read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004602 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004603{
Michal Vasko53b7da02018-02-13 15:28:42 +01004604 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004605 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004606 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 struct lyxml_elem *sub, *next;
4608 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004609 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004610 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004611 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 leaf = calloc(1, sizeof *leaf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004614 LY_CHECK_ERR_RETURN(!leaf, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004615
Radek Krejci76512572015-08-04 09:47:08 +02004616 leaf->nodetype = LYS_LEAF;
4617 leaf->prev = (struct lys_node *)leaf;
4618 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004619
Radek Krejci07d0fb92017-01-13 14:11:05 +01004620 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004621 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4622 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4623 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 goto error;
4625 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004626
Michal Vasko3e3228d2017-02-24 14:55:32 +01004627 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004628
Radek Krejcic189a952016-07-11 15:27:07 +02004629 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004630 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004631 goto error;
4632 }
4633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004635 if (strcmp(sub->ns->value, LY_NSYIN)) {
4636 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004637 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004638 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004639 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004640 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004641 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004642 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 goto error;
4644 }
Michal Vasko88c29542015-11-27 14:57:53 +01004645 /* HACK for unres */
4646 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004647 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004648 /* postpone type resolution when if-feature parsing is done since we need
4649 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004650 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 } else if (!strcmp(sub->name, "default")) {
4652 if (leaf->dflt) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004653 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 goto error;
4655 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004656 GETVAL(ctx, value, sub, "value");
4657 leaf->dflt = lydict_insert(ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004658
Radek Krejci8d6b7422017-02-03 14:42:13 +01004659 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004660 goto error;
4661 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 } else if (!strcmp(sub->name, "units")) {
4663 if (leaf->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004664 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 goto error;
4666 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004667 GETVAL(ctx, value, sub, "name");
4668 leaf->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004669
Radek Krejci8d6b7422017-02-03 14:42:13 +01004670 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004671 goto error;
4672 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 } else if (!strcmp(sub->name, "mandatory")) {
4674 if (f_mand) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004675 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 goto error;
4677 }
4678 /* just checking the flags in leaf is not sufficient, we would allow
4679 * multiple mandatory statements with the "false" value
4680 */
4681 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004682
Michal Vasko53b7da02018-02-13 15:28:42 +01004683 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004685 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004686 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004687 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004688 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004689 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 goto error;
4691 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004692
Radek Krejci8d6b7422017-02-03 14:42:13 +01004693 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004694 goto error;
4695 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004696 } else if (!strcmp(sub->name, "when")) {
4697 if (leaf->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004698 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004699 goto error;
4700 }
4701
Radek Krejci5323b492017-01-16 15:40:11 +01004702 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004703 if (!leaf->when) {
4704 goto error;
4705 }
4706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004708 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, leaf->must_size, "musts", "leaf", error);
Radek Krejci41882de2015-07-02 16:34:58 +02004709 c_must++;
4710 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004711 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004712 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "musts", "leaf", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004713 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004717 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004720
Michal Vasko88c29542015-11-27 14:57:53 +01004721 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004725 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004726 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
Michal Vasko478c4652016-07-21 12:55:01 +02004729 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004730 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4731 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004732 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4733 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 /* middle part - process nodes with cardinality of 0..n */
4737 if (c_must) {
4738 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01004739 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004741 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004742 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01004743 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004744 }
Radek Krejcie534c132016-11-23 13:32:31 +01004745 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004746 /* some extensions may be already present from the substatements */
4747 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01004748 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004749 retval->ext = reallocated;
4750
4751 /* init memory */
4752 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004753 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004754
Radek Krejcie534c132016-11-23 13:32:31 +01004755 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4756 if (strcmp(sub->ns->value, LY_NSYIN)) {
4757 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08004758 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 +01004759 if (r) {
4760 goto error;
4761 }
4762 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004763 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004764 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 if (r) {
4766 goto error;
4767 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004768 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004769 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004770 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004771 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004772 goto error;
4773 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004776
fanchanghufb4152e2021-01-21 20:56:39 +08004777 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
4778
Radek Krejcicbb473e2016-09-16 14:48:32 +02004779 /* finalize type parsing */
4780 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4781 leaf->type.der = NULL;
4782 goto error;
4783 }
4784
4785 /* check default value (if not defined, there still could be some restrictions
4786 * that need to be checked against a default value from a derived type) */
Michal Vasko6a057782018-03-09 13:24:33 +01004787 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01004788 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4789 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004790 goto error;
4791 }
4792
Michal Vasko508a50d2016-09-07 14:50:33 +02004793 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01004794 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004795 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004796 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004797 goto error;
4798 }
4799 } else {
4800 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4801 goto error;
4802 }
4803 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004804 }
4805
PavolVican92f23622017-12-12 13:35:56 +01004806 for (r = 0; r < retval->ext_size; ++r) {
4807 /* set flag, which represent LYEXT_OPT_VALID */
Michal Vaskoa3917d92021-03-08 14:08:05 +01004808 if (retval->ext[r] && (retval->ext[r]->flags & LYEXT_OPT_VALID)) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01004809 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01004810 break;
4811 }
4812 }
4813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004815
4816error:
Michal Vasko5ce30802021-03-08 09:34:04 +01004817 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004818 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004819}
4820
Michal Vasko0d343d12015-08-24 14:57:36 +02004821/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004822static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004823read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004824 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004825{
Michal Vasko53b7da02018-02-13 15:28:42 +01004826 struct ly_ctx *ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02004827 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004828 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004829 struct lyxml_elem *sub, *next;
4830 const char *value;
4831 char *endptr;
4832 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004833 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004834 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004836 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 llist = calloc(1, sizeof *llist);
Michal Vasko53b7da02018-02-13 15:28:42 +01004839 LY_CHECK_ERR_RETURN(!llist, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004840
Radek Krejci76512572015-08-04 09:47:08 +02004841 llist->nodetype = LYS_LEAFLIST;
4842 llist->prev = (struct lys_node *)llist;
4843 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004844
Radek Krejci07d0fb92017-01-13 14:11:05 +01004845 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004846 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4847 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4848 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 goto error;
4850 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004851
Michal Vasko3e3228d2017-02-24 14:55:32 +01004852 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004853
Radek Krejcic189a952016-07-11 15:27:07 +02004854 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004855 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004856 goto error;
4857 }
4858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004860 if (strcmp(sub->ns->value, LY_NSYIN)) {
4861 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01004862 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "leaf-list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01004863 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004864 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004865 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004866 if (has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004867 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 goto error;
4869 }
Michal Vasko88c29542015-11-27 14:57:53 +01004870 /* HACK for unres */
4871 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004872 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004873 /* postpone type resolution when if-feature parsing is done since we need
4874 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004875 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 } else if (!strcmp(sub->name, "units")) {
4877 if (llist->units) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004878 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 goto error;
4880 }
Michal Vasko53b7da02018-02-13 15:28:42 +01004881 GETVAL(ctx, value, sub, "name");
4882 llist->units = lydict_insert(ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004883
Radek Krejci8d6b7422017-02-03 14:42:13 +01004884 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004885 goto error;
4886 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 } else if (!strcmp(sub->name, "ordered-by")) {
4888 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004889 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 goto error;
4891 }
4892 /* just checking the flags in llist is not sufficient, we would
4893 * allow multiple ordered-by statements with the "system" value
4894 */
4895 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004896
Radek Krejci1574a8d2015-08-03 14:16:52 +02004897 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4899 * state data
4900 */
Michal Vasko53b7da02018-02-13 15:28:42 +01004901 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 continue;
4903 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004904
Michal Vasko53b7da02018-02-13 15:28:42 +01004905 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004907 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004909 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004910 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004911 } /* else system is the default value, so we can ignore it */
4912
Radek Krejci8d6b7422017-02-03 14:42:13 +01004913 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004914 goto error;
4915 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004917 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, llist->must_size, "musts", "leaf-list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004918 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004919 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004920 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004921 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "leaf-list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004922 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004923 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004924 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004925 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004926 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 +01004927 goto error;
4928 }
4929
Michal Vasko53b7da02018-02-13 15:28:42 +01004930 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dflt, llist->dflt_size, "defaults", "leaf-list", error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02004931 c_dflt++;
4932 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004934 } else if (!strcmp(sub->name, "min-elements")) {
4935 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004936 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 goto error;
4938 }
4939 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004940
Michal Vasko53b7da02018-02-13 15:28:42 +01004941 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 while (isspace(value[0])) {
4943 value++;
4944 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946 /* convert it to uint32_t */
4947 errno = 0;
4948 endptr = NULL;
4949 val = strtoul(value, &endptr, 10);
4950 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004951 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 goto error;
4953 }
4954 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004955 if (llist->max && (llist->min > llist->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004956 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4957 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004958 goto error;
4959 }
Radek Krejci5323b492017-01-16 15:40:11 +01004960
Radek Krejci8d6b7422017-02-03 14:42:13 +01004961 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004962 goto error;
4963 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 } else if (!strcmp(sub->name, "max-elements")) {
4965 if (f_max) {
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_max = 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 Krejci0d7b2472016-02-12 11:11:03 +01004976 if (!strcmp(value, "unbounded")) {
4977 llist->max = 0;
4978 } else {
4979 /* convert it to uint32_t */
4980 errno = 0;
4981 endptr = NULL;
4982 val = strtoul(value, &endptr, 10);
4983 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004984 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004985 goto error;
4986 }
4987 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004988 if (llist->min > llist->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004989 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4990 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004991 goto error;
4992 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004993 }
Radek Krejci5323b492017-01-16 15:40:11 +01004994
Radek Krejci8d6b7422017-02-03 14:42:13 +01004995 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004996 goto error;
4997 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004998 } else if (!strcmp(sub->name, "when")) {
4999 if (llist->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005000 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005001 goto error;
5002 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005003
Radek Krejci5323b492017-01-16 15:40:11 +01005004 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005005 if (!llist->when) {
5006 goto error;
5007 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005009 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005011 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005012
Michal Vasko88c29542015-11-27 14:57:53 +01005013 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005014 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005017 if (!has_type) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005018 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 goto error;
5020 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005022 /* middle part - process nodes with cardinality of 0..n */
5023 if (c_must) {
5024 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005025 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005026 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005027 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005028 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005029 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005030 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005031 if (c_dflt) {
5032 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01005033 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005034 }
Radek Krejcie534c132016-11-23 13:32:31 +01005035 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01005036 /* some extensions may be already present from the substatements */
5037 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005038 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci5323b492017-01-16 15:40:11 +01005039 retval->ext = reallocated;
5040
5041 /* init memory */
5042 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005043 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02005044
Radek Krejcie534c132016-11-23 13:32:31 +01005045 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5046 if (strcmp(sub->ns->value, LY_NSYIN)) {
5047 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08005048 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 +01005049 if (r) {
5050 goto error;
5051 }
5052 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005053 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005054 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 if (r) {
5056 goto error;
5057 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005058 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005059 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005060 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005061 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005062 goto error;
5063 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005064 } else if (!strcmp(sub->name, "default")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005065 GETVAL(ctx, value, sub, "value");
Radek Krejcid5a5c282016-08-15 15:38:08 +02005066
Radek Krejciac1a52c2016-09-15 14:42:40 +02005067 /* check for duplicity in case of configuration data,
5068 * in case of status data duplicities are allowed */
5069 if (llist->flags & LYS_CONFIG_W) {
5070 for (r = 0; r < llist->dflt_size; r++) {
5071 if (ly_strequal(llist->dflt[r], value, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005072 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, "default");
5073 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02005074 goto error;
5075 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02005076 }
5077 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005078 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005079 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005080 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005081
fanchanghufb4152e2021-01-21 20:56:39 +08005082 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
5083
Radek Krejcicbb473e2016-09-16 14:48:32 +02005084 /* finalize type parsing */
5085 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
5086 llist->type.der = NULL;
5087 goto error;
5088 }
5089
Radek Krejcid5a5c282016-08-15 15:38:08 +02005090 if (llist->dflt_size && llist->min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005091 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
5092 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005093 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5094 goto error;
5095 }
5096
5097 /* check default value (if not defined, there still could be some restrictions
5098 * that need to be checked against a default value from a derived type) */
5099 for (r = 0; r < llist->dflt_size; r++) {
Michal Vasko6a057782018-03-09 13:24:33 +01005100 if (!(ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01005101 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5102 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005103 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005104 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005105 }
5106
Michal Vasko508a50d2016-09-07 14:50:33 +02005107 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005108 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (llist->when || llist->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005109 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005110 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005111 goto error;
5112 }
5113 } else {
5114 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5115 goto error;
5116 }
5117 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005118 }
5119
PavolVican92f23622017-12-12 13:35:56 +01005120 for (r = 0; r < retval->ext_size; ++r) {
5121 /* set flag, which represent LYEXT_OPT_VALID */
Michal Vaskoa3917d92021-03-08 14:08:05 +01005122 if (retval->ext[r] && (retval->ext[r]->flags & LYEXT_OPT_VALID)) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005123 retval->flags |= LYS_VALID_EXT;
PavolVican92f23622017-12-12 13:35:56 +01005124 break;
5125 }
5126 }
5127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005128 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005129
5130error:
Michal Vasko5ce30802021-03-08 09:34:04 +01005131 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005132 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005133}
5134
Michal Vasko0d343d12015-08-24 14:57:36 +02005135/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005136static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005137read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005138 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005139{
Michal Vasko53b7da02018-02-13 15:28:42 +01005140 struct ly_ctx *ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005141 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005142 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005143 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005144 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005145 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005146 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005147 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005148 char *auxs;
5149 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005150 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005152 /* init */
5153 memset(&root, 0, sizeof root);
5154 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005156 list = calloc(1, sizeof *list);
Michal Vasko53b7da02018-02-13 15:28:42 +01005157 LY_CHECK_ERR_RETURN(!list, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005158
Radek Krejci76512572015-08-04 09:47:08 +02005159 list->nodetype = LYS_LIST;
5160 list->prev = (struct lys_node *)list;
5161 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005162
Radek Krejci07d0fb92017-01-13 14:11:05 +01005163 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005164 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5165 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5166 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 goto error;
5168 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005169
Michal Vasko3e3228d2017-02-24 14:55:32 +01005170 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005171
Radek Krejcic189a952016-07-11 15:27:07 +02005172 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005173 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005174 goto error;
5175 }
5176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 /* process list's specific children */
5178 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005179 if (strcmp(sub->ns->value, LY_NSYIN)) {
5180 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005181 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "list", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005182 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005183 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005186 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005187 !strcmp(sub->name, "leaf-list") ||
5188 !strcmp(sub->name, "leaf") ||
5189 !strcmp(sub->name, "list") ||
5190 !strcmp(sub->name, "choice") ||
5191 !strcmp(sub->name, "uses") ||
5192 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005193 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005194 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005195 !strcmp(sub->name, "action") ||
5196 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005197 lyxml_unlink_elem(ctx, sub, 2);
5198 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 /* array counters */
5201 } else if (!strcmp(sub->name, "key")) {
5202 /* check cardinality 0..1 */
5203 if (list->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005204 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 goto error;
5206 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 /* count the number of keys */
Michal Vasko53b7da02018-02-13 15:28:42 +01005209 GETVAL(ctx, value, sub, "value");
5210 list->keys_str = lydict_insert(ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 while ((value = strpbrk(value, " \t\n"))) {
5212 list->keys_size++;
5213 while (isspace(*value)) {
5214 value++;
5215 }
5216 }
5217 list->keys_size++;
5218 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01005219 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005220
Radek Krejci8d6b7422017-02-03 14:42:13 +01005221 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005222 goto error;
5223 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005224 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 } else if (!strcmp(sub->name, "unique")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005226 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_uniq, list->unique_size, "uniques", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005227 c_uniq++;
Michal Vasko53b7da02018-02-13 15:28:42 +01005228 lyxml_unlink_elem(ctx, sub, 2);
5229 lyxml_add_child(ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005231 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, list->tpdf_size, "typedefs", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005232 c_tpdf++;
5233 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005234 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, list->must_size, "musts", "list", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005235 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005236 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005237 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "list", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005238 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005240 /* optional stetments */
5241 } else if (!strcmp(sub->name, "ordered-by")) {
5242 if (f_ordr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005243 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005244 goto error;
5245 }
5246 /* just checking the flags in llist is not sufficient, we would
5247 * allow multiple ordered-by statements with the "system" value
5248 */
5249 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005250
Radek Krejci1574a8d2015-08-03 14:16:52 +02005251 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005252 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5253 * state data
5254 */
Michal Vasko53b7da02018-02-13 15:28:42 +01005255 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005256 continue;
5257 }
Radek Krejci345ad742015-06-03 11:04:18 +02005258
Michal Vasko53b7da02018-02-13 15:28:42 +01005259 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005260 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005261 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005262 } else if (strcmp(value, "system")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005263 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005265 } /* else system is the default value, so we can ignore it */
5266
Radek Krejci8d6b7422017-02-03 14:42:13 +01005267 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005268 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005270 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 } else if (!strcmp(sub->name, "min-elements")) {
5272 if (f_min) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005273 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 goto error;
5275 }
5276 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005277
Michal Vasko53b7da02018-02-13 15:28:42 +01005278 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 while (isspace(value[0])) {
5280 value++;
5281 }
Radek Krejci345ad742015-06-03 11:04:18 +02005282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005283 /* convert it to uint32_t */
5284 errno = 0;
5285 auxs = NULL;
5286 val = strtoul(value, &auxs, 10);
5287 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005288 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 goto error;
5290 }
5291 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005292 if (list->max && (list->min > list->max)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005293 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5294 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
5295 lyxml_free(ctx, sub);
Michal Vasko6ea3e362016-03-11 10:25:36 +01005296 goto error;
5297 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005298 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005299 goto error;
5300 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005301 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005302 } else if (!strcmp(sub->name, "max-elements")) {
5303 if (f_max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005304 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005305 goto error;
5306 }
5307 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005308
Michal Vasko53b7da02018-02-13 15:28:42 +01005309 GETVAL(ctx, value, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005310 while (isspace(value[0])) {
5311 value++;
5312 }
Radek Krejci345ad742015-06-03 11:04:18 +02005313
Radek Krejci0d7b2472016-02-12 11:11:03 +01005314 if (!strcmp(value, "unbounded")) {
5315 list->max = 0;;
5316 } else {
5317 /* convert it to uint32_t */
5318 errno = 0;
5319 auxs = NULL;
5320 val = strtoul(value, &auxs, 10);
5321 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005322 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005323 goto error;
5324 }
5325 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005326 if (list->min > list->max) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005327 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
5328 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005329 goto error;
5330 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005331 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005332 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005333 goto error;
5334 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005335 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005336 } else if (!strcmp(sub->name, "when")) {
5337 if (list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005338 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005339 goto error;
5340 }
5341
Radek Krejci5323b492017-01-16 15:40:11 +01005342 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005343 if (!list->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005344 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005345 goto error;
5346 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005347 lyxml_free(ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005348 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005349 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005350 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005351 }
5352 }
Radek Krejci345ad742015-06-03 11:04:18 +02005353
Michal Vaskoe022a562016-09-27 14:24:15 +02005354 /* check - if list is configuration, key statement is mandatory
5355 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005356 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005357 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005358 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005359 goto error;
5360 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005362 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5363 if (c_tpdf) {
5364 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005365 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005367 if (c_must) {
5368 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005369 LY_CHECK_ERR_GOTO(!list->must, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005370 }
5371 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005372 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005373 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005374 }
Radek Krejcie534c132016-11-23 13:32:31 +01005375 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005376 /* some extensions may be already present from the substatements */
5377 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005378 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005379 retval->ext = reallocated;
5380
5381 /* init memory */
5382 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005383 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005384
Radek Krejcie534c132016-11-23 13:32:31 +01005385 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5386 if (strcmp(sub->ns->value, LY_NSYIN)) {
5387 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08005388 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 +01005389 if (r) {
5390 goto error;
5391 }
5392 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005393 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5394 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005395 if (r) {
5396 goto error;
5397 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005398 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005399 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005400 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005401 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005402 goto error;
5403 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005404 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005405 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005406 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005407 if (r) {
5408 goto error;
5409 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005410 }
5411 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005412
fanchanghufb4152e2021-01-21 20:56:39 +08005413 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
5414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005415 /* last part - process data nodes */
5416 LY_TREE_FOR_SAFE(root.child, next, sub) {
5417 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005418 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005419 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005420 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005421 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005422 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005423 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005424 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005426 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005428 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005429 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005430 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005431 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005432 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005433 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005434 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005435 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005436 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005437 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005438 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005439 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005440 LOGINT(ctx);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005441 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005442 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005443 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005444 goto error;
5445 }
Radek Krejci73adb602015-07-02 18:07:40 +02005446
Michal Vasko53b7da02018-02-13 15:28:42 +01005447 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005448 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005449
Radek Krejci5c08a992016-11-02 13:30:04 +01005450 if (list->keys_str) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02005451 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005452 goto error;
5453 }
5454 } /* 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 +02005455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005456 /* process unique statements */
5457 if (c_uniq) {
5458 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01005459 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005460
Radek Krejci461efb92016-02-12 15:52:18 +01005461 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5462 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5463 list->unique_size++;
5464 if (r) {
5465 goto error;
5466 }
5467
Radek Krejci8d6b7422017-02-03 14:42:13 +01005468 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005469 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5470 goto error;
5471 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005472 lyxml_free(ctx, sub);
Radek Krejci461efb92016-02-12 15:52:18 +01005473 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005474 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005475
Michal Vasko508a50d2016-09-07 14:50:33 +02005476 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005477 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005478 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005479 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005480 goto error;
5481 }
5482 } else {
5483 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5484 goto error;
5485 }
5486 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005487 }
5488
PavolVican92f23622017-12-12 13:35:56 +01005489 for (r = 0; r < retval->ext_size; ++r) {
5490 /* set flag, which represent LYEXT_OPT_VALID */
Michal Vaskoa3917d92021-03-08 14:08:05 +01005491 if (retval->ext[r] && (retval->ext[r]->flags & LYEXT_OPT_VALID)) {
Michal Vasko1bdfd432018-03-09 09:30:19 +01005492 retval->flags |= LYS_VALID_EXT;
Robin Jarry8d820d32019-04-06 12:26:13 +02005493 if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
5494 retval->flags |= LYS_VALID_EXT_SUBTREE;
5495 break;
5496 }
PavolVican92f23622017-12-12 13:35:56 +01005497 }
5498 }
5499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005500 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005501
5502error:
5503
Michal Vasko5ce30802021-03-08 09:34:04 +01005504 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005505 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005506 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005507 }
5508 while (uniq.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005509 lyxml_free(ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005510 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005512 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005513}
5514
Michal Vasko0d343d12015-08-24 14:57:36 +02005515/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005516static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005517read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005518 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005519{
Michal Vasko53b7da02018-02-13 15:28:42 +01005520 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005521 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005522 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005523 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005524 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005525 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005526 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005527 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005528 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005530 /* init */
5531 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005533 cont = calloc(1, sizeof *cont);
Michal Vasko53b7da02018-02-13 15:28:42 +01005534 LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005535
Radek Krejci76512572015-08-04 09:47:08 +02005536 cont->nodetype = LYS_CONTAINER;
5537 cont->prev = (struct lys_node *)cont;
5538 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005539
Radek Krejci07d0fb92017-01-13 14:11:05 +01005540 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005541 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5542 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5543 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005544 goto error;
5545 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005546
Michal Vasko3e3228d2017-02-24 14:55:32 +01005547 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005548
Radek Krejcic189a952016-07-11 15:27:07 +02005549 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005550 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005551 goto error;
5552 }
5553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005554 /* process container's specific children */
5555 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005556 if (strcmp(sub->ns->value, LY_NSYIN)) {
5557 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005558 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005559 c_ext++;
5560 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005561 if (cont->presence) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005562 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005563 goto error;
5564 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005565 GETVAL(ctx, value, sub, "value");
5566 cont->presence = lydict_insert(ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005567
Radek Krejci8d6b7422017-02-03 14:42:13 +01005568 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005569 goto error;
5570 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005571 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005572 } else if (!strcmp(sub->name, "when")) {
5573 if (cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005574 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005575 goto error;
5576 }
5577
Radek Krejci5323b492017-01-16 15:40:11 +01005578 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005579 if (!cont->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005580 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005581 goto error;
5582 }
Michal Vasko53b7da02018-02-13 15:28:42 +01005583 lyxml_free(ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005585 /* data statements */
5586 } else if (!strcmp(sub->name, "container") ||
5587 !strcmp(sub->name, "leaf-list") ||
5588 !strcmp(sub->name, "leaf") ||
5589 !strcmp(sub->name, "list") ||
5590 !strcmp(sub->name, "choice") ||
5591 !strcmp(sub->name, "uses") ||
5592 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005593 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005594 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005595 !strcmp(sub->name, "action") ||
5596 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005597 lyxml_unlink_elem(ctx, sub, 2);
5598 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005600 /* array counters */
5601 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005602 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005603 c_tpdf++;
5604 } else if (!strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005605 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005606 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005607 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005608 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005609 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005611 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005612 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005613 }
5614 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005616 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5617 if (c_tpdf) {
5618 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005619 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005620 }
5621 if (c_must) {
5622 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005623 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005624 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005625 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005626 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01005627 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005628 }
Radek Krejcie534c132016-11-23 13:32:31 +01005629 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005630 /* some extensions may be already present from the substatements */
5631 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005632 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005633 retval->ext = reallocated;
5634
5635 /* init memory */
5636 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005637 }
Radek Krejci800af702015-06-02 13:46:01 +02005638
Radek Krejcie534c132016-11-23 13:32:31 +01005639 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5640 if (strcmp(sub->ns->value, LY_NSYIN)) {
5641 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08005642 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 +01005643 if (r) {
5644 goto error;
5645 }
5646 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005647 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5648 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005649 if (r) {
5650 goto error;
5651 }
5652 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005653 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005654 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005655 if (r) {
5656 goto error;
5657 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005658 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005659 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005660 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005661 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005662 goto error;
5663 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005664 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005665 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005666
fanchanghufb4152e2021-01-21 20:56:39 +08005667 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
5668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 /* last part - process data nodes */
5670 LY_TREE_FOR_SAFE(root.child, next, sub) {
5671 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005672 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005673 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005674 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005675 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005676 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005677 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005678 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005679 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005680 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005681 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005682 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005683 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005684 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005685 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005686 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005687 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005688 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005689 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005690 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005691 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005692 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005693 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005694 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005695 goto error;
5696 }
Radek Krejci73adb602015-07-02 18:07:40 +02005697
Michal Vasko53b7da02018-02-13 15:28:42 +01005698 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005699 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005700
Michal Vasko508a50d2016-09-07 14:50:33 +02005701 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01005702 if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005703 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005704 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005705 goto error;
5706 }
5707 } else {
5708 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5709 goto error;
5710 }
5711 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005712 }
5713
PavolVican92f23622017-12-12 13:35:56 +01005714 for (r = 0; r < retval->ext_size; ++r) {
Michal Vaskoa3917d92021-03-08 14:08:05 +01005715 /* extension instance may not yet be resolved */
5716 if (retval->ext[r] && (retval->ext[r]->flags & LYEXT_OPT_VALID)) {
5717 /* set flag, which represent LYEXT_OPT_VALID */
Michal Vasko1bdfd432018-03-09 09:30:19 +01005718 retval->flags |= LYS_VALID_EXT;
Robin Jarry8d820d32019-04-06 12:26:13 +02005719 if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
5720 retval->flags |= LYS_VALID_EXT_SUBTREE;
5721 break;
5722 }
PavolVican92f23622017-12-12 13:35:56 +01005723 }
5724 }
5725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005726 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005727
5728error:
Michal Vasko5ce30802021-03-08 09:34:04 +01005729 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005730 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005731 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005732 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005733 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005734}
5735
Michal Vasko0d343d12015-08-24 14:57:36 +02005736/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005737static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005738read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005739 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005740{
Michal Vasko53b7da02018-02-13 15:28:42 +01005741 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005742 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005743 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005744 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005745 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005746 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005747 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005748 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005750 /* init */
5751 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005753 grp = calloc(1, sizeof *grp);
Michal Vasko53b7da02018-02-13 15:28:42 +01005754 LY_CHECK_ERR_RETURN(!grp, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005755
Radek Krejci76512572015-08-04 09:47:08 +02005756 grp->nodetype = LYS_GROUPING;
5757 grp->prev = (struct lys_node *)grp;
5758 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005759
Radek Krejci07d0fb92017-01-13 14:11:05 +01005760 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005761 goto error;
5762 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005763
Michal Vasko3e3228d2017-02-24 14:55:32 +01005764 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005765
Radek Krejcic189a952016-07-11 15:27:07 +02005766 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005767 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005768 goto error;
5769 }
5770
Radek Krejci1d82ef62015-08-07 14:44:40 +02005771 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005772 if (strcmp(sub->ns->value, LY_NSYIN)) {
5773 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005774 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "grouping", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005775 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005777 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005778 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005779 !strcmp(sub->name, "leaf-list") ||
5780 !strcmp(sub->name, "leaf") ||
5781 !strcmp(sub->name, "list") ||
5782 !strcmp(sub->name, "choice") ||
5783 !strcmp(sub->name, "uses") ||
5784 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005785 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005786 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005787 !strcmp(sub->name, "action") ||
5788 !strcmp(sub->name, "notification")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005789 lyxml_unlink_elem(ctx, sub, 2);
5790 lyxml_add_child(ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005792 /* array counters */
5793 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005794 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, grp->tpdf_size, "typedefs", "grouping", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005795 c_tpdf++;
5796 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005797 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005798 goto error;
5799 }
5800 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005802 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5803 if (c_tpdf) {
5804 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005805 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005806 }
Radek Krejcie534c132016-11-23 13:32:31 +01005807 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005808 /* some extensions may be already present from the substatements */
5809 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005810 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005811 retval->ext = reallocated;
5812
5813 /* init memory */
5814 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005815 }
Radek Krejcie534c132016-11-23 13:32:31 +01005816 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5817 if (strcmp(sub->ns->value, LY_NSYIN)) {
5818 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08005819 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 +01005820 if (r) {
5821 goto error;
5822 }
5823 } else {
5824 /* typedef */
5825 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5826 grp->tpdf_size++;
5827 if (r) {
5828 goto error;
5829 }
5830 }
5831 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005832
fanchanghufb4152e2021-01-21 20:56:39 +08005833 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
5834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005835 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005836 if (!root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005837 LOGWRN(ctx, "Grouping \"%s\" without children.", retval->name);
Michal Vasko919dbbc2016-05-19 15:22:45 +02005838 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005839 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005840 LY_TREE_FOR_SAFE(root.child, next, sub) {
5841 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005842 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005843 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005844 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005845 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005846 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005847 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005848 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005849 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005850 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005851 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005852 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005853 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005854 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005855 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005856 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005857 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005858 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005859 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005860 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005861 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005862 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005863 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005864 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005865 goto error;
5866 }
Radek Krejci73adb602015-07-02 18:07:40 +02005867
Michal Vasko53b7da02018-02-13 15:28:42 +01005868 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005869 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005871 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005872
5873error:
Michal Vasko5ce30802021-03-08 09:34:04 +01005874 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005875 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005876 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005877 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005878 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005879}
5880
Michal Vasko0d343d12015-08-24 14:57:36 +02005881/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005882static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005883read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005884 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005885{
Michal Vasko53b7da02018-02-13 15:28:42 +01005886 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02005887 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005888 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005889 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005890 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005891 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005892 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005893
Radek Krejcie0674f82015-06-15 13:58:51 +02005894 /* init */
5895 memset(&root, 0, sizeof root);
5896
Michal Vasko38d01f72015-06-15 09:41:06 +02005897 inout = calloc(1, sizeof *inout);
Michal Vasko53b7da02018-02-13 15:28:42 +01005898 LY_CHECK_ERR_RETURN(!inout, LOGMEM(ctx), NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005899 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005900
5901 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005902 inout->nodetype = LYS_INPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005903 inout->name = lydict_insert(ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005904 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005905 inout->nodetype = LYS_OUTPUT;
Michal Vasko53b7da02018-02-13 15:28:42 +01005906 inout->name = lydict_insert(ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005907 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005908 LOGINT(ctx);
Radek Krejci6acc8012015-08-13 09:07:04 +02005909 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005910 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005911 }
5912
Radek Krejci76512572015-08-04 09:47:08 +02005913 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005914 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005915
Michal Vasko3e3228d2017-02-24 14:55:32 +01005916 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005917
Radek Krejcic189a952016-07-11 15:27:07 +02005918 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02005919 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02005920 goto error;
5921 }
5922
Michal Vasko38d01f72015-06-15 09:41:06 +02005923 /* data statements */
5924 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005925 if (!sub->ns) {
5926 /* garbage */
Michal Vasko53b7da02018-02-13 15:28:42 +01005927 lyxml_free(ctx, sub);
Radek Krejcie7770892017-01-24 13:18:01 +01005928 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005929 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01005930 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02005931 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejcie534c132016-11-23 13:32:31 +01005932 c_ext++;
5933 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005934 !strcmp(sub->name, "leaf-list") ||
5935 !strcmp(sub->name, "leaf") ||
5936 !strcmp(sub->name, "list") ||
5937 !strcmp(sub->name, "choice") ||
5938 !strcmp(sub->name, "uses") ||
5939 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005940 !strcmp(sub->name, "anyxml") ||
5941 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005942 lyxml_unlink_elem(ctx, sub, 2);
5943 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005945 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005946 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005947 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, inout->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02005948 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005949 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005950
Radek Krejci1a31efe2016-07-29 11:04:16 +02005951 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005952 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, inout->must_size, "musts",
Radek Krejcidce5f972017-09-12 15:47:49 +02005953 inout->nodetype == LYS_INPUT ? "input" : "output", error);
Radek Krejci19332802016-07-29 10:39:46 +02005954 c_must++;
5955
Michal Vasko38d01f72015-06-15 09:41:06 +02005956 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01005957 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005958 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005959 }
5960 }
5961
Michal Vaskob04e5a82020-01-03 15:54:36 +01005962 if (!root.child) {
5963 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "schema-node", strnodetype(retval->nodetype));
5964 goto error;
5965 }
5966
Michal Vasko38d01f72015-06-15 09:41:06 +02005967 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5968 if (c_tpdf) {
5969 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005970 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005971 }
Radek Krejci19332802016-07-29 10:39:46 +02005972 if (c_must) {
5973 inout->must = calloc(c_must, sizeof *inout->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01005974 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM(ctx), error);
Radek Krejci19332802016-07-29 10:39:46 +02005975 }
Radek Krejcie534c132016-11-23 13:32:31 +01005976 if (c_ext) {
5977 inout->ext = calloc(c_ext, sizeof *inout->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01005978 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM(ctx), error);
Radek Krejcie534c132016-11-23 13:32:31 +01005979 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005980
Radek Krejcie534c132016-11-23 13:32:31 +01005981 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5982 if (strcmp(sub->ns->value, LY_NSYIN)) {
5983 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08005984 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 +01005985 if (r) {
5986 goto error;
5987 }
5988 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005989 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005990 inout->must_size++;
5991 if (r) {
5992 goto error;
5993 }
5994 } else { /* typedef */
5995 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5996 inout->tpdf_size++;
5997 if (r) {
5998 goto error;
5999 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006000 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006001 }
6002
fanchanghufb4152e2021-01-21 20:56:39 +08006003 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
6004
Michal Vasko38d01f72015-06-15 09:41:06 +02006005 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006006 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02006007 LY_TREE_FOR_SAFE(root.child, next, sub) {
6008 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006009 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006010 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006011 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006012 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006013 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006014 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006015 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006016 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006017 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006018 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006019 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006020 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006021 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006022 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006023 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006024 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006025 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006026 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006027 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006028 goto error;
6029 }
Radek Krejci73adb602015-07-02 18:07:40 +02006030
Michal Vasko53b7da02018-02-13 15:28:42 +01006031 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006032 }
6033
Michal Vasko508a50d2016-09-07 14:50:33 +02006034 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006035 if (!(ctx->models.flags & LY_CTX_TRUSTED) && inout->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006036 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006037 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006038 goto error;
6039 }
6040 } else {
6041 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6042 goto error;
6043 }
6044 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006045 }
6046
Michal Vasko38d01f72015-06-15 09:41:06 +02006047 return retval;
6048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006049error:
Michal Vasko5ce30802021-03-08 09:34:04 +01006050 lys_node_free(ctx, retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006051 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006052 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006053 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006054 return NULL;
6055}
6056
Michal Vasko0d343d12015-08-24 14:57:36 +02006057/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006058static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006059read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006060 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02006061{
Michal Vasko53b7da02018-02-13 15:28:42 +01006062 struct ly_ctx *ctx = module->ctx;
Michal Vaskoc6551b32015-06-16 10:51:43 +02006063 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006064 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006065 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006066 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006067 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006068 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01006069 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02006070
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006071 if (parent && (module->version < 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006072 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02006073 return NULL;
6074 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006075
Michal Vaskoc6551b32015-06-16 10:51:43 +02006076 memset(&root, 0, sizeof root);
6077
Michal Vasko0ea41032015-06-16 08:53:55 +02006078 notif = calloc(1, sizeof *notif);
Michal Vasko53b7da02018-02-13 15:28:42 +01006079 LY_CHECK_ERR_RETURN(!notif, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006080
Radek Krejci76512572015-08-04 09:47:08 +02006081 notif->nodetype = LYS_NOTIF;
6082 notif->prev = (struct lys_node *)notif;
6083 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02006084
Radek Krejci07d0fb92017-01-13 14:11:05 +01006085 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006086 goto error;
6087 }
6088
Michal Vasko3e3228d2017-02-24 14:55:32 +01006089 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006090
Radek Krejcic189a952016-07-11 15:27:07 +02006091 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006092 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006093 goto error;
6094 }
6095
Michal Vasko0ea41032015-06-16 08:53:55 +02006096 /* process rpc's specific children */
6097 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006098 if (strcmp(sub->ns->value, LY_NSYIN)) {
6099 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006100 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "notification", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006101 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006102 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006103
Michal Vasko0ea41032015-06-16 08:53:55 +02006104 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006105 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006106 !strcmp(sub->name, "leaf-list") ||
6107 !strcmp(sub->name, "leaf") ||
6108 !strcmp(sub->name, "list") ||
6109 !strcmp(sub->name, "choice") ||
6110 !strcmp(sub->name, "uses") ||
6111 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006112 !strcmp(sub->name, "anyxml") ||
6113 !strcmp(sub->name, "anydata")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006114 lyxml_unlink_elem(ctx, sub, 2);
6115 lyxml_add_child(ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006117 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006118 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006119 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, notif->tpdf_size, "typedefs", "notification", error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006120 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006121 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006122 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "notification", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006123 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006124 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006125 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, notif->must_size, "musts", "notification", error);
Radek Krejci19332802016-07-29 10:39:46 +02006126 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006127 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006128 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006129 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006130 }
6131 }
6132
6133 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6134 if (c_tpdf) {
6135 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006136 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006137 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006138 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006139 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006140 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006141 }
Radek Krejci19332802016-07-29 10:39:46 +02006142 if (c_must) {
6143 notif->must = calloc(c_must, sizeof *notif->must);
Michal Vasko53b7da02018-02-13 15:28:42 +01006144 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM(ctx), error);
Michal Vasko0ea41032015-06-16 08:53:55 +02006145 }
Radek Krejcie534c132016-11-23 13:32:31 +01006146 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006147 /* some extensions may be already present from the substatements */
6148 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006149 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01006150 retval->ext = reallocated;
6151
6152 /* init memory */
6153 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006154 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006155
Radek Krejcie534c132016-11-23 13:32:31 +01006156 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6157 if (strcmp(sub->ns->value, LY_NSYIN)) {
6158 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08006159 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 +01006160 if (r) {
6161 goto error;
6162 }
6163 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006164 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6165 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006166 if (r) {
6167 goto error;
6168 }
Radek Krejci96299152016-06-22 10:17:50 +02006169 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006170 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006171 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006172 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006173 goto error;
6174 }
Radek Krejci19332802016-07-29 10:39:46 +02006175 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006176 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006177 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006178 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006179 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006180 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006181 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006182 }
6183
fanchanghufb4152e2021-01-21 20:56:39 +08006184 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
6185
Michal Vasko0ea41032015-06-16 08:53:55 +02006186 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006187 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006188 LY_TREE_FOR_SAFE(root.child, next, sub) {
6189 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006190 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006191 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006192 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006193 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006194 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006195 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006196 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006197 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006198 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006199 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006200 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006201 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006202 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006203 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006204 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006205 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006206 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006207 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006208 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006209 goto error;
6210 }
Radek Krejci73adb602015-07-02 18:07:40 +02006211
Michal Vasko53b7da02018-02-13 15:28:42 +01006212 lyxml_free(ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006213 }
6214
Michal Vasko508a50d2016-09-07 14:50:33 +02006215 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006216 if (!(ctx->models.flags & LY_CTX_TRUSTED) && notif->must) {
Michal Vasko89afc112017-03-16 13:57:28 +01006217 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006218 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006219 goto error;
6220 }
6221 } else {
6222 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6223 goto error;
6224 }
6225 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006226 }
6227
Michal Vasko0ea41032015-06-16 08:53:55 +02006228 return retval;
6229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006230error:
Michal Vasko5ce30802021-03-08 09:34:04 +01006231 lys_node_free(ctx, retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006232 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006233 lyxml_free(ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006234 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006235 return NULL;
6236}
6237
Michal Vasko0d343d12015-08-24 14:57:36 +02006238/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006239static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006240read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006241 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006242{
Michal Vasko53b7da02018-02-13 15:28:42 +01006243 struct ly_ctx *ctx = module->ctx;
Radek Krejcie0674f82015-06-15 13:58:51 +02006244 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006245 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006246 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006247 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006248 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006249 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006250 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006251
Michal Vasko8fa6ec22020-03-05 15:29:26 +01006252 if (!strcmp(yin->name, "action") && (module->version < 2)) {
6253 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, parent, "action");
6254 return NULL;
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006255 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006256
Radek Krejcie0674f82015-06-15 13:58:51 +02006257 /* init */
6258 memset(&root, 0, sizeof root);
6259
Michal Vasko38d01f72015-06-15 09:41:06 +02006260 rpc = calloc(1, sizeof *rpc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006261 LY_CHECK_ERR_RETURN(!rpc, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006262
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006263 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006264 rpc->prev = (struct lys_node *)rpc;
6265 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006266
Radek Krejci07d0fb92017-01-13 14:11:05 +01006267 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006268 goto error;
6269 }
6270
Michal Vasko3e3228d2017-02-24 14:55:32 +01006271 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006272
Radek Krejcic189a952016-07-11 15:27:07 +02006273 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006274 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006275 goto error;
6276 }
6277
Michal Vasko38d01f72015-06-15 09:41:06 +02006278 /* process rpc's specific children */
6279 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006280 if (strcmp(sub->ns->value, LY_NSYIN)) {
6281 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006282 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006283 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006284 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006285 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006286 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006287 if (c_input) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006288 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006289 goto error;
6290 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006291 c_input++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006292 lyxml_unlink_elem(ctx, sub, 2);
6293 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006294 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006295 if (c_output) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006296 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006297 goto error;
6298 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006299 c_output++;
Michal Vasko53b7da02018-02-13 15:28:42 +01006300 lyxml_unlink_elem(ctx, sub, 2);
6301 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006303 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006304 } else if (!strcmp(sub->name, "grouping")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006305 lyxml_unlink_elem(ctx, sub, 2);
6306 lyxml_add_child(ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006308 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006309 } else if (!strcmp(sub->name, "typedef")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006310 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, rpc->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006311 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006312 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006313 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006314 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006315 rpc->nodetype == LYS_RPC ? "rpc" : "action", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006316 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006317 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006318 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006319 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006320 }
6321 }
6322
6323 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6324 if (c_tpdf) {
6325 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006326 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM(ctx), error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006327 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006328 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006329 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006330 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006331 }
Radek Krejcie534c132016-11-23 13:32:31 +01006332 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006333 /* some extensions may be already present from the substatements */
6334 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006335 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006336 retval->ext = reallocated;
6337
6338 /* init memory */
6339 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006340 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006341
Radek Krejcie534c132016-11-23 13:32:31 +01006342 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6343 if (strcmp(sub->ns->value, LY_NSYIN)) {
6344 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08006345 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, &retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006346 if (r) {
6347 goto error;
6348 }
6349 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006350 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6351 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006352 if (r) {
6353 goto error;
6354 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006355 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006356 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006357 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006358 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006359 goto error;
6360 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006361 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006362 }
6363
fanchanghufb4152e2021-01-21 20:56:39 +08006364 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
6365
Michal Vasko38d01f72015-06-15 09:41:06 +02006366 /* last part - process data nodes */
6367 LY_TREE_FOR_SAFE(root.child, next, sub) {
6368 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006369 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006370 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006371 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006372 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006373 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006374 goto error;
6375 }
Radek Krejci73adb602015-07-02 18:07:40 +02006376
Michal Vasko53b7da02018-02-13 15:28:42 +01006377 lyxml_free(ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006378 }
6379
Michal Vasko38d01f72015-06-15 09:41:06 +02006380 return retval;
6381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006382error:
Michal Vasko5ce30802021-03-08 09:34:04 +01006383 lys_node_free(ctx, retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006384 while (root.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006385 lyxml_free(ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006386 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006387 return NULL;
6388}
6389
Michal Vasko0d343d12015-08-24 14:57:36 +02006390/* logs directly
6391 *
Radek Krejci74705112015-06-05 10:25:44 +02006392 * resolve - referenced grouping should be bounded to the namespace (resolved)
6393 * only when uses does not appear in grouping. In a case of grouping's uses,
6394 * we just get information but we do not apply augment or refine to it.
6395 */
Radek Krejci76512572015-08-04 09:47:08 +02006396static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006397read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6398 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006399{
Michal Vasko53b7da02018-02-13 15:28:42 +01006400 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006401 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006402 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006403 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006404 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006405 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006406 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006407 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006409 uses = calloc(1, sizeof *uses);
Michal Vasko53b7da02018-02-13 15:28:42 +01006410 LY_CHECK_ERR_RETURN(!uses, LOGMEM(ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006411
Radek Krejci76512572015-08-04 09:47:08 +02006412 uses->nodetype = LYS_USES;
6413 uses->prev = (struct lys_node *)uses;
6414 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006415
Michal Vasko53b7da02018-02-13 15:28:42 +01006416 GETVAL(ctx, value, yin, "name");
6417 uses->name = lydict_insert(ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006418
Radek Krejci07d0fb92017-01-13 14:11:05 +01006419 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006420 goto error;
6421 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006422
Michal Vasko3e3228d2017-02-24 14:55:32 +01006423 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006424
Radek Krejcic189a952016-07-11 15:27:07 +02006425 /* insert the node into the schema tree */
Michal Vasko8d30dd82018-09-10 10:06:12 +02006426 if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
Radek Krejcic189a952016-07-11 15:27:07 +02006427 goto error;
6428 }
6429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006430 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006431 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006432 if (strcmp(sub->ns->value, LY_NSYIN)) {
6433 /* extension */
Michal Vasko53b7da02018-02-13 15:28:42 +01006434 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "uses", error);
Radek Krejcie534c132016-11-23 13:32:31 +01006435 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006436 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006437 } else if (!strcmp(sub->name, "refine")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006438 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ref, uses->refine_size, "refines", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006439 c_ref++;
6440 } else if (!strcmp(sub->name, "augment")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006441 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, uses->augment_size, "augments", "uses", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006442 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006443 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006444 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "uses", error);
Radek Krejci56e89772015-06-19 10:00:54 +02006445 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006446 } else if (!strcmp(sub->name, "when")) {
6447 if (uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006448 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006449 goto error;
6450 }
6451
Radek Krejci5323b492017-01-16 15:40:11 +01006452 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006453 if (!uses->when) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006454 lyxml_free(ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006455 goto error;
6456 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006457 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006458 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006459 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006460 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006461 }
6462 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006464 /* process properties with cardinality 0..n */
6465 if (c_ref) {
6466 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko53b7da02018-02-13 15:28:42 +01006467 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006468 }
6469 if (c_aug) {
6470 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01006471 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006472 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006473 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006474 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01006475 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006476 }
Radek Krejcie534c132016-11-23 13:32:31 +01006477 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006478 /* some extensions may be already present from the substatements */
6479 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01006480 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006481 retval->ext = reallocated;
6482
6483 /* init memory */
6484 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006485 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006486
Radek Krejcie534c132016-11-23 13:32:31 +01006487 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6488 if (strcmp(sub->ns->value, LY_NSYIN)) {
6489 /* extension */
fanchanghufb4152e2021-01-21 20:56:39 +08006490 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 +01006491 if (r) {
6492 goto error;
6493 }
6494 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006495 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006496 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006497 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006498 goto error;
6499 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006500 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006501 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006502 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006503 if (r) {
6504 goto error;
6505 }
6506 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006507 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006508 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006509 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006510 goto error;
6511 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006512 }
6513 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006514
fanchanghufb4152e2021-01-21 20:56:39 +08006515 lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);
6516
Radek Krejci48464ed2016-03-17 15:44:09 +01006517 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006518 goto error;
6519 }
Radek Krejci74705112015-06-05 10:25:44 +02006520
Michal Vasko508a50d2016-09-07 14:50:33 +02006521 /* check XPath dependencies */
Michal Vasko53b7da02018-02-13 15:28:42 +01006522 if (!(ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01006523 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006524 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006525 goto error;
6526 }
6527 } else {
6528 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6529 goto error;
6530 }
6531 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006532 }
6533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006534 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006535
6536error:
Michal Vasko5ce30802021-03-08 09:34:04 +01006537 lys_node_free(ctx, retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006538 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006539}
6540
Michal Vasko0d343d12015-08-24 14:57:36 +02006541/* logs directly
6542 *
6543 * common code for yin_read_module() and yin_read_submodule()
6544 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006545static int
Radek Krejcic071c542016-01-27 14:57:51 +01006546read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6547 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006548{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006549 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006550 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006551 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006552 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006553 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006554 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006555 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006556 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6557 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6558 int substmt_group;
6559 /* just remember last substatement for logging */
6560 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006561 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006562 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;
6563 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006564 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006565
Radek Krejcic071c542016-01-27 14:57:51 +01006566 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006567 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006569 /* init */
6570 memset(&root, 0, sizeof root);
6571 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006572 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006573 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006574 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006576 /*
6577 * in the first run, we process elements with cardinality of 1 or 0..1 and
6578 * count elements with cardinality 0..n. Data elements (choices, containers,
6579 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6580 * need have all top-level and groupings already prepared at that time. In
6581 * the middle loop, we process other elements with carinality of 0..n since
6582 * we need to allocate arrays to store them.
6583 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006584 substmt_group = 0;
6585 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006586 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006587 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006588 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006589 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006590 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006591 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006592 /* possible extension instance */
Michal Vasko53b7da02018-02-13 15:28:42 +01006593 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_extinst, trg->ext_size, "extension instances",
Radek Krejcidce5f972017-09-12 15:47:49 +02006594 submodule ? "submodule" : "module", error);
Michal Vasko53b7da02018-02-13 15:28:42 +01006595 lyxml_unlink_elem(ctx, child, 2);
6596 lyxml_add_child(ctx, &exts, child);
Radek Krejcie534c132016-11-23 13:32:31 +01006597 c_extinst++;
6598 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006599 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006600 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6601 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006602 child->name, substmt_prev);
6603 goto error;
6604 }
6605
PavolVican9e81c6a2017-02-09 13:09:07 +01006606 if (trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006607 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006608 goto error;
6609 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006610 GETVAL(ctx, value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006611 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006612
Radek Krejci8d6b7422017-02-03 14:42:13 +01006613 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006614 goto error;
6615 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006616 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006617
6618 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006619 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006620 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006621 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6622 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006623 child->name, substmt_prev);
6624 goto error;
6625 }
6626
PavolVican9e81c6a2017-02-09 13:09:07 +01006627 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006628 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006629 goto error;
6630 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006631 GETVAL(ctx, value, child, "value");
6632 if (lyp_check_identifier(ctx, value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006633 goto error;
6634 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006635 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006636
Radek Krejci8d6b7422017-02-03 14:42:13 +01006637 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006638 goto error;
6639 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006640 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006641
6642 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006643 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006644 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006645 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6646 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006647 child->name, substmt_prev);
6648 goto error;
6649 }
6650
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006651 if (trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006652 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006653 goto error;
6654 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006655 GETVAL(ctx, value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006656 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006657 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006658 goto error;
6659 }
Radek Krejcif3886932015-06-04 17:36:06 +02006660
Radek Krejci8d6b7422017-02-03 14:42:13 +01006661 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006662 goto error;
6663 }
6664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006665 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006666 if (!child->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006667 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006668 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006669 } else if (strcmp(child->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006670 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006671 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006672 } else if (child->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006673 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006674 goto error;
6675 }
6676 /* and now finally get the value */
Michal Vasko53b7da02018-02-13 15:28:42 +01006677 GETVAL(ctx, value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006678 /* check here differs from a generic prefix check, since this prefix
6679 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006680 */
Michal Vasko53b7da02018-02-13 15:28:42 +01006681 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006682 goto error;
6683 }
Radek Krejcic071c542016-01-27 14:57:51 +01006684 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006685
Radek Krejci8d6b7422017-02-03 14:42:13 +01006686 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 +01006687 goto error;
6688 }
6689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006690 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006691 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006692
Michal Vasko5de8a022017-02-08 10:57:26 +01006693 substmt_prev = "belongs-to";
6694
Radek Krejcieb00f512015-07-01 16:44:58 +02006695 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006696 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006697 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006698 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6699 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006700 child->name, substmt_prev);
6701 goto error;
6702 }
6703 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006704 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_imp, trg->imp_size, "imports",
Radek Krejcidce5f972017-09-12 15:47:49 +02006705 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006706 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006707
6708 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006709 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006710 if (substmt_group > 3) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006711 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6712 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006713 child->name, substmt_prev);
6714 goto error;
6715 }
6716 substmt_group = 3;
Michal Vasko53b7da02018-02-13 15:28:42 +01006717 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_rev, trg->rev_size, "revisions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006718 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006719 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006720
PavolVican9e81c6a2017-02-09 13:09:07 +01006721 lyxml_unlink_elem(ctx, child, 2);
6722 lyxml_add_child(ctx, &revs, child);
6723
Michal Vasko5de8a022017-02-08 10:57:26 +01006724 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006725 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006726 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006727 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, trg->tpdf_size, "typedefs",
Radek Krejcidce5f972017-09-12 15:47:49 +02006728 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006729 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006730
6731 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006732 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006733 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006734 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ident, trg->ident_size, "identities",
Radek Krejcidce5f972017-09-12 15:47:49 +02006735 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006736 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006737
6738 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006739 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006740 if (substmt_group > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006741 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6742 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006743 child->name, substmt_prev);
6744 goto error;
6745 }
6746 substmt_group = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +01006747 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_inc, trg->inc_size, "includes",
Radek Krejcidce5f972017-09-12 15:47:49 +02006748 submodule ? "submodule" : "module", error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006749 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006750
6751 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006752 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006753 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006754 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_aug, trg->augment_size, "augments",
Radek Krejcidce5f972017-09-12 15:47:49 +02006755 submodule ? "submodule" : "module", error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006756 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006757 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006758 lyxml_unlink_elem(ctx, child, 2);
6759 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006760
Michal Vasko5de8a022017-02-08 10:57:26 +01006761 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006762 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006763 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006764 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, trg->features_size, "features",
Radek Krejcidce5f972017-09-12 15:47:49 +02006765 submodule ? "submodule" : "module", error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006766 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006767
Michal Vasko5de8a022017-02-08 10:57:26 +01006768 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006770 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006771 } else if (!strcmp(child->name, "container") ||
6772 !strcmp(child->name, "leaf-list") ||
6773 !strcmp(child->name, "leaf") ||
6774 !strcmp(child->name, "list") ||
6775 !strcmp(child->name, "choice") ||
6776 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006777 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006778 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006779 !strcmp(child->name, "rpc") ||
6780 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006781 substmt_group = 4;
6782
Radek Krejcic071c542016-01-27 14:57:51 +01006783 lyxml_unlink_elem(ctx, child, 2);
6784 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006785
Michal Vasko5de8a022017-02-08 10:57:26 +01006786 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006787 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006788 substmt_group = 4;
6789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006790 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006791 lyxml_unlink_elem(ctx, child, 2);
6792 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006793
Michal Vasko5de8a022017-02-08 10:57:26 +01006794 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006795 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006796 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006797 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006798 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6799 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006800 child->name, substmt_prev);
6801 goto error;
6802 }
6803 substmt_group = 2;
6804
Radek Krejcic071c542016-01-27 14:57:51 +01006805 if (trg->dsc) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006806 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006807 goto error;
6808 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006809 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006810 goto error;
6811 }
Radek Krejcic071c542016-01-27 14:57:51 +01006812 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006813 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006814 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006815 goto error;
6816 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006817
6818 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006819 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006820 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006821 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6822 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006823 child->name, substmt_prev);
6824 goto error;
6825 }
6826 substmt_group = 2;
6827
Radek Krejcic071c542016-01-27 14:57:51 +01006828 if (trg->ref) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006829 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006830 goto error;
6831 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006832 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006833 goto error;
6834 }
Radek Krejcic071c542016-01-27 14:57:51 +01006835 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006836 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006837 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006838 goto error;
6839 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006840
6841 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006842 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006843 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006844 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6845 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006846 child->name, substmt_prev);
6847 goto error;
6848 }
6849 substmt_group = 2;
6850
Radek Krejcic071c542016-01-27 14:57:51 +01006851 if (trg->org) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006852 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006853 goto error;
6854 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006855 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006856 goto error;
6857 }
Radek Krejcic071c542016-01-27 14:57:51 +01006858 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006859 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006860 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006861 goto error;
6862 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006863
6864 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006865 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006866 if (substmt_group > 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006867 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6868 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006869 child->name, substmt_prev);
6870 goto error;
6871 }
6872 substmt_group = 2;
6873
Radek Krejcic071c542016-01-27 14:57:51 +01006874 if (trg->contact) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006875 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006876 goto error;
6877 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006878 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006879 goto error;
6880 }
Radek Krejcic071c542016-01-27 14:57:51 +01006881 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006882 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006883 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006884 goto error;
6885 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006886
6887 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006888 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006889 if (substmt_group > 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006890 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6891 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
Michal Vasko5de8a022017-02-08 10:57:26 +01006892 child->name, substmt_prev);
6893 goto error;
6894 }
6895
Radek Krejcic071c542016-01-27 14:57:51 +01006896 if (version_flag) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006897 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006898 goto error;
6899 }
Michal Vasko53b7da02018-02-13 15:28:42 +01006900 GETVAL(ctx, value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006901 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006902 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006903 goto error;
6904 }
Radek Krejcic071c542016-01-27 14:57:51 +01006905 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006906 if (!strcmp(value, "1")) {
6907 if (submodule) {
6908 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006909 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006910 goto error;
6911 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006912 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006913 } else {
6914 module->version = 1;
6915 }
6916 } else {
6917 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006918 if (module->version < 2) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006919 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Michal Vasko88de3e42016-06-29 11:05:32 +02006920 goto error;
6921 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006922 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006923 } else {
6924 module->version = 2;
6925 }
6926 }
6927
Radek Krejci8d6b7422017-02-03 14:42:13 +01006928 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006929 goto error;
6930 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006931 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006932
Michal Vasko5de8a022017-02-08 10:57:26 +01006933 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006934 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006935 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006936 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, trg->extensions_size, "extensions",
Radek Krejcidce5f972017-09-12 15:47:49 +02006937 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006938 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006939
Michal Vasko5de8a022017-02-08 10:57:26 +01006940 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006941 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006942 substmt_group = 4;
Michal Vasko53b7da02018-02-13 15:28:42 +01006943 YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_dev, trg->deviation_size, "deviations",
Radek Krejcidce5f972017-09-12 15:47:49 +02006944 submodule ? "submodule" : "module", error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006945 c_dev++;
6946
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006947 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006948 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01006949 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006950 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006951 }
6952 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006953
Radek Krejcic071c542016-01-27 14:57:51 +01006954 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006955 if (submodule) {
6956 if (!submodule->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006957 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006958 goto error;
6959 }
6960 if (!version_flag) {
6961 /* check version compatibility with the main module */
6962 if (module->version > 1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006963 LOGVAL(ctx, LYE_INVER, LY_VLOG_NONE, NULL);
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006964 goto error;
6965 }
6966 }
6967 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006968 if (!trg->ns) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006969 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006970 goto error;
6971 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006972 if (!trg->prefix) {
Michal Vasko53b7da02018-02-13 15:28:42 +01006973 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006974 goto error;
6975 }
6976 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006978 /* allocate arrays for elements with cardinality of 0..n */
6979 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006980 trg->imp = calloc(c_imp, sizeof *trg->imp);
Michal Vasko53b7da02018-02-13 15:28:42 +01006981 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006982 }
6983 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006984 trg->rev = calloc(c_rev, sizeof *trg->rev);
Michal Vasko53b7da02018-02-13 15:28:42 +01006985 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006986 }
6987 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006988 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Michal Vasko53b7da02018-02-13 15:28:42 +01006989 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006990 }
6991 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006992 trg->ident = calloc(c_ident, sizeof *trg->ident);
Michal Vasko53b7da02018-02-13 15:28:42 +01006993 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006994 }
6995 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006996 trg->inc = calloc(c_inc, sizeof *trg->inc);
Michal Vasko53b7da02018-02-13 15:28:42 +01006997 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM(ctx), error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006998 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006999 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01007000 trg->augment = calloc(c_aug, sizeof *trg->augment);
Michal Vasko53b7da02018-02-13 15:28:42 +01007001 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM(ctx), error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007002 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02007003 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01007004 trg->features = calloc(c_ftrs, sizeof *trg->features);
Michal Vasko53b7da02018-02-13 15:28:42 +01007005 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM(ctx), error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02007006 }
Radek Krejcieb00f512015-07-01 16:44:58 +02007007 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01007008 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Michal Vasko53b7da02018-02-13 15:28:42 +01007009 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM(ctx), error);
Radek Krejcieb00f512015-07-01 16:44:58 +02007010 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09007011 if (c_ext) {
7012 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Michal Vasko53b7da02018-02-13 15:28:42 +01007013 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM(ctx), error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007014 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007015
PavolVican9e81c6a2017-02-09 13:09:07 +01007016 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
7017 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01007018 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
7019 trg->rev_size++;
7020 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007021 goto error;
7022 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007023
Radek Krejci7417a082017-02-16 11:07:59 +01007024 /* check uniqueness of the revision date - not required by RFC */
7025 for (i = 0; i < (trg->rev_size - 1); i++) {
7026 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007027 LOGWRN(ctx, "Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
Radek Krejci7417a082017-02-16 11:07:59 +01007028 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01007029 }
7030 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007031
7032 lyxml_free(ctx, child);
7033 }
7034
7035 /* check the module with respect to the context now */
7036 if (!submodule) {
7037 switch (lyp_ctx_check_module(module)) {
7038 case -1:
7039 goto error;
7040 case 0:
7041 break;
7042 case 1:
7043 /* it's already there */
7044 ret = 1;
7045 goto error;
7046 }
7047 }
7048
PavolVican92f23622017-12-12 13:35:56 +01007049 /* check first definition of extensions */
7050 if (c_ext) {
7051 LY_TREE_FOR_SAFE(yin->child, next, child) {
7052 if (!strcmp(child->name, "extension")) {
7053 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
7054 trg->extensions_size++;
7055 if (r) {
7056 goto error;
7057 }
7058
7059 }
7060 }
7061 }
7062
PavolVican9e81c6a2017-02-09 13:09:07 +01007063 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007064 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007065 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007066 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007067 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007068 if (r) {
7069 goto error;
7070 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007071
Radek Krejci1d82ef62015-08-07 14:44:40 +02007072 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007073 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7074 trg->inc_size++;
7075 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007076 goto error;
7077 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007078
Radek Krejci1d82ef62015-08-07 14:44:40 +02007079 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007080 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7081 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007082 if (r) {
7083 goto error;
7084 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007085
Radek Krejci1d82ef62015-08-07 14:44:40 +02007086 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007087 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7088 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007089 if (r) {
7090 goto error;
7091 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007092
Radek Krejci1d82ef62015-08-07 14:44:40 +02007093 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007094 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7095 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007096 if (r) {
7097 goto error;
7098 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007099
Radek Krejci1d82ef62015-08-07 14:44:40 +02007100 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko0f437062018-06-08 15:52:39 +02007101 /* must be implemented in this case */
7102 trg->implemented = 1;
7103
Radek Krejcic071c542016-01-27 14:57:51 +01007104 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7105 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007106 if (r) {
7107 goto error;
7108 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007109 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007110 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007111
Radek Krejcie534c132016-11-23 13:32:31 +01007112 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007113 if (c_extinst) {
7114 /* some extensions may be already present from the substatements */
7115 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01007116 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
Radek Krejci8ee94802017-02-10 12:38:40 +01007117 trg->ext = reallocated;
7118
7119 /* init memory */
7120 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7121
7122 LY_TREE_FOR_SAFE(exts.child, next, child) {
fanchanghufb4152e2021-01-21 20:56:39 +08007123 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, &trg->ext_size, unres);
Radek Krejci8ee94802017-02-10 12:38:40 +01007124 if (r) {
7125 goto error;
7126 }
7127 }
fanchanghufb4152e2021-01-21 20:56:39 +08007128
7129 lyp_reduce_ext_list(&trg->ext, trg->ext_size, c_ext + trg->ext_size);
Radek Krejcie534c132016-11-23 13:32:31 +01007130 }
7131
Radek Krejcif5be10f2015-06-16 13:29:36 +02007132 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007133 * refer to them. Submodule's data nodes are stored in the
7134 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007135 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007136 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007137 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007138 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007139 goto error;
7140 }
Radek Krejci74705112015-06-05 10:25:44 +02007141
Michal Vasko345da0a2015-12-02 10:35:55 +01007142 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007143 }
Radek Krejci74705112015-06-05 10:25:44 +02007144
Radek Krejcif5be10f2015-06-16 13:29:36 +02007145 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007146 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007147
Radek Krejci1d82ef62015-08-07 14:44:40 +02007148 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007149 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007150 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007151 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007152 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007153 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007154 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007155 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007156 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007157 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007158 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007159 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007160 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007161 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007162 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007163 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007164 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007165 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007166 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007167 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007168 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007169 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007170 goto error;
7171 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007172
Michal Vasko345da0a2015-12-02 10:35:55 +01007173 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007174 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007175
Michal Vasko2f7925f2015-10-21 15:06:56 +02007176 /* ... and finally augments (last, so we can augment our data, for instance) */
7177 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007178 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007179 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007180
Michal Vasko2f7925f2015-10-21 15:06:56 +02007181 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007182 goto error;
7183 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007184 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007185 }
7186
PavolVican9e81c6a2017-02-09 13:09:07 +01007187 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007188
7189error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007190 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007191 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007192 }
7193 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007194 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007195 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007196 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007197 lyxml_free(ctx, augs.child);
7198 }
7199 while (revs.child) {
7200 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007201 }
Radek Krejcie534c132016-11-23 13:32:31 +01007202 while (exts.child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007203 lyxml_free(ctx, exts.child);
Radek Krejcie534c132016-11-23 13:32:31 +01007204 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007205
PavolVican9e81c6a2017-02-09 13:09:07 +01007206 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007207}
7208
Michal Vasko0d343d12015-08-24 14:57:36 +02007209/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007210struct lys_submodule *
7211yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007212{
Michal Vasko53b7da02018-02-13 15:28:42 +01007213 struct ly_ctx *ctx = module->ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007214 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007215 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007216 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007217
Michal Vasko53b7da02018-02-13 15:28:42 +01007218 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007219 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007220 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007221 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007223 /* check root element */
7224 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007225 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007226 goto error;
7227 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007228
Michal Vasko53b7da02018-02-13 15:28:42 +01007229 GETVAL(ctx, value, yin, "name");
7230 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007231 goto error;
7232 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007233
Michal Vasko5a721fd2016-02-16 12:16:48 +01007234 submodule = calloc(1, sizeof *submodule);
Michal Vasko53b7da02018-02-13 15:28:42 +01007235 LY_CHECK_ERR_GOTO(!submodule, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007236
Michal Vasko53b7da02018-02-13 15:28:42 +01007237 submodule->ctx = ctx;
7238 submodule->name = lydict_insert(ctx, value, strlen(value));
Michal Vasko5a721fd2016-02-16 12:16:48 +01007239 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02007240 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007241 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007242
Radek Krejci9e757e02017-03-08 17:18:09 +01007243 /* add into the list of processed modules */
7244 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7245 goto error;
7246 }
7247
Michal Vasko5a721fd2016-02-16 12:16:48 +01007248 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007249 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007250 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007251 goto error;
7252 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007253
Radek Krejci33fc4772017-01-26 16:00:35 +01007254 lyp_sort_revisions((struct lys_module *)submodule);
7255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007256 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007257 lyxml_free(ctx, yin);
7258 lyp_check_circmod_pop(ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007259
Michal Vasko5a721fd2016-02-16 12:16:48 +01007260 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007261 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007262
7263error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007264 /* cleanup */
Michal Vasko53b7da02018-02-13 15:28:42 +01007265 lyxml_free(ctx, yin);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007266 if (!submodule) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007267 LOGERR(ctx, ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007268 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007269 }
7270
Michal Vasko53b7da02018-02-13 15:28:42 +01007271 LOGERR(ctx, ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007272
Michal Vaskoa9728122018-01-16 14:00:13 +01007273 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko53b7da02018-02-13 15:28:42 +01007274 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007275 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7276 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007277 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007278 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007279}
7280
Michal Vasko0d343d12015-08-24 14:57:36 +02007281/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007282struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007283yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007284{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007285 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007286 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007287 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007288 int ret;
Michal Vasko7d4c0172020-01-20 14:21:35 +01007289 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02007290
Radek Krejcic071c542016-01-27 14:57:51 +01007291 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01007292 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007294 /* check root element */
7295 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007296 if (ly_strequal("submodule", yin->name, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007297 LOGVAL(ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007298 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007299 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007300 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007301 goto error;
7302 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007303
Michal Vasko53b7da02018-02-13 15:28:42 +01007304 GETVAL(ctx, value, yin, "name");
7305 if (lyp_check_identifier(ctx, value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007306 goto error;
7307 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007308
Michal Vasko7d4c0172020-01-20 14:21:35 +01007309 /* in some really invalid situations there can be a circular import and
7310 * we can check it only after we have parsed the module name */
7311 for (i = 0; i < ctx->models.parsing_sub_modules_count; ++i) {
7312 if (!strcmp(ctx->models.parsing_sub_modules[i]->name, value)) {
7313 LOGVAL(ctx, LYE_CIRC_IMPORTS, LY_VLOG_NONE, NULL, value);
7314 goto error;
7315 }
7316 }
7317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007318 module = calloc(1, sizeof *module);
Michal Vasko53b7da02018-02-13 15:28:42 +01007319 LY_CHECK_ERR_GOTO(!module, LOGMEM(ctx), error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007321 module->ctx = ctx;
7322 module->name = lydict_insert(ctx, value, strlen(value));
7323 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007324 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007325
Radek Krejci9e757e02017-03-08 17:18:09 +01007326 /* add into the list of processed modules */
7327 if (lyp_check_circmod_add(module)) {
7328 goto error;
7329 }
7330
Michal Vasko9f258e42016-02-11 11:36:27 +01007331 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007332 ret = read_sub_module(module, NULL, yin, unres);
7333 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007334 goto error;
7335 }
7336
PavolVican9e81c6a2017-02-09 13:09:07 +01007337 if (ret == 1) {
7338 assert(!unres->count);
7339 } else {
Michal Vasko0f437062018-06-08 15:52:39 +02007340 /* make this module implemented if was not from start */
7341 if (!implement && module->implemented && (unres_schema_add_node(module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1)) {
7342 goto error;
7343 }
7344
PavolVican9e81c6a2017-02-09 13:09:07 +01007345 /* resolve rest of unres items */
7346 if (unres->count && resolve_unres_schema(module, unres)) {
7347 goto error;
7348 }
7349
7350 /* check correctness of includes */
7351 if (lyp_check_include_missing(module)) {
7352 goto error;
7353 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007354 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007355
Radek Krejci95f22ae2017-01-20 14:25:53 +01007356 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007357
7358 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7359 goto error;
7360 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007361
Radek Krejciff4874d2016-03-07 12:30:50 +01007362 if (revision) {
7363 /* check revision of the parsed model */
7364 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007365 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7366 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007367 goto error;
7368 }
7369 }
7370
PavolVican9e81c6a2017-02-09 13:09:07 +01007371 /* add into context if not already there */
7372 if (!ret) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007373 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007374 goto error;
7375 }
Michal Vasko10681e82018-01-16 14:54:16 +01007376
7377 /* remove our submodules from the parsed submodules list */
7378 lyp_del_includedup(module, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007379 } else {
7380 /* free what was parsed */
Michal Vasko10681e82018-01-16 14:54:16 +01007381 lys_free(module, NULL, 0, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007382
7383 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007384 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007385 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007386 }
7387
Michal Vasko44ab1462017-05-18 13:18:36 +02007388 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007389 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02007390 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
7391 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007392 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007393
7394error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007395 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007396 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007397
7398 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007399 if (ly_vecode(ctx) != LYVE_SUBMODULE) {
7400 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007401 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007402 return NULL;
7403 }
7404
Michal Vasko53b7da02018-02-13 15:28:42 +01007405 LOGERR(ctx, ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007406
Radek Krejci9e757e02017-03-08 17:18:09 +01007407 lyp_check_circmod_pop(ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007408 lys_sub_module_remove_devs_augs(module);
Michal Vasko10681e82018-01-16 14:54:16 +01007409 lyp_del_includedup(module, 1);
7410 lys_free(module, NULL, 0, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007411 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007412}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007413
Radek Krejci37f9ba32017-02-10 16:50:35 +01007414/* logs directly */
7415struct lys_module *
7416yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7417{
7418 struct lyxml_elem *yin;
7419 struct lys_module *result;
7420
Radek Krejcie1bacd72017-03-01 13:18:46 +01007421 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007422 if (!yin) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007423 LOGERR(ctx, ly_errno, "Module parsing failed.");
Radek Krejci37f9ba32017-02-10 16:50:35 +01007424 return NULL;
7425 }
7426
7427 result = yin_read_module_(ctx, yin, revision, implement);
7428
7429 lyxml_free(ctx, yin);
7430
7431 return result;
7432}
7433
Radek Krejcic1885952017-02-07 09:37:51 +01007434static int
7435yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007436 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007437 const char *true_val, const char *false_val, struct unres_schema *unres)
7438{
7439 uint8_t *val;
7440 const char *str;
7441 struct lyext_substmt *info;
7442
7443 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7444 if (!val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007445 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007446 return EXIT_FAILURE;
7447 }
7448 if (*val) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007449 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007450 return EXIT_FAILURE;
7451 }
7452
Radek Krejcidb35f172017-02-27 11:03:01 +01007453 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007454 return EXIT_FAILURE;
7455 }
7456
7457 str = lyxml_get_attr(node, "value", NULL);
7458 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007459 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007460 } else if (true_val && !strcmp(true_val, str)) {
7461 /* true value */
7462 *val = 1;
7463 } else if (false_val && !strcmp(false_val, str)) {
7464 /* false value */
7465 *val = 2;
7466 } else {
7467 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007468 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007469 return EXIT_FAILURE;
7470 }
7471
7472 return EXIT_SUCCESS;
7473}
7474
Radek Krejci8d6b7422017-02-03 14:42:13 +01007475/*
7476 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7477 * argname - name of the element/attribute where the value is stored
7478 */
7479static int
7480yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007481 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007482 int argelem, const char *argname, struct unres_schema *unres)
7483{
7484 int c;
PavolVican99c70722017-02-18 17:25:52 +01007485 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007486 void *reallocated;
7487 struct lyext_substmt *info;
7488
7489 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7490 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007491 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007492 return EXIT_FAILURE;
7493 }
7494 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007495 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007496 return EXIT_FAILURE;
7497 }
7498
7499 c = 0;
7500 if (info->cardinality >= LY_STMT_CARD_SOME) {
7501 /* there can be multiple instances, str is actually const char *** */
7502 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007503 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007504 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007505 p[0] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007506 LY_CHECK_ERR_RETURN(!p[0], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007507 if (stmt == LY_STMT_BELONGSTO) {
7508 /* allocate another array for the belongs-to's prefixes */
7509 p[1] = malloc(2 * sizeof(const char *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007510 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007511 } else if (stmt == LY_STMT_ARGUMENT) {
7512 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007513 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Michal Vasko53b7da02018-02-13 15:28:42 +01007514 LY_CHECK_ERR_RETURN(!p[1], LOGMEM(mod->ctx), EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007515 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007516 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007517 /* get the index in the array to add new item */
7518 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007519 }
Radek Krejci56c80412017-02-09 10:44:16 +01007520 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007521 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007522 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007523 return EXIT_FAILURE;
7524 }
7525
7526 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007527 str[c] = read_yin_subnode(mod->ctx, node, argname);
7528 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007529 return EXIT_FAILURE;
7530 }
Radek Krejci56c80412017-02-09 10:44:16 +01007531 } else {
7532 str[c] = lyxml_get_attr(node, argname, NULL);
7533 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007534 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007535 return EXIT_FAILURE;
7536 } else {
7537 str[c] = lydict_insert(mod->ctx, str[c], 0);
7538 }
7539
7540 if (stmt == LY_STMT_BELONGSTO) {
7541 /* get the belongs-to's mandatory prefix substatement */
7542 if (!node->child) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007543 LOGVAL(mod->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007544 return EXIT_FAILURE;
7545 } else if (strcmp(node->child->name, "prefix")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007546 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007547 return EXIT_FAILURE;
7548 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007549 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007550 return EXIT_FAILURE;
7551 }
7552 /* and now finally get the value */
7553 if (p) {
7554 str = p[1];
7555 } else {
7556 str++;
7557 }
7558 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7559 if (!str[c]) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007560 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
Radek Krejci56c80412017-02-09 10:44:16 +01007561 return EXIT_FAILURE;
7562 }
7563 str[c] = lydict_insert(mod->ctx, str[c], 0);
7564
PavolVican6d400872017-03-01 15:19:18 +01007565 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 +01007566 return EXIT_FAILURE;
7567 }
PavolVican99c70722017-02-18 17:25:52 +01007568 } else if (stmt == LY_STMT_ARGUMENT) {
7569 str = (p) ? p[1] : str + 1;
7570 if (!node->child) {
7571 /* default value of yin element */
7572 ((uint8_t *)str)[c] = 2;
7573 } else {
7574 /* get optional yin-element substatement */
7575 if (strcmp(node->child->name, "yin-element")) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007576 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007577 return EXIT_FAILURE;
7578 } else if (node->child->next) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007579 LOGVAL(mod->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
PavolVican99c70722017-02-18 17:25:52 +01007580 return EXIT_FAILURE;
7581 } else {
7582 /* and now finally get the value */
7583 value = lyxml_get_attr(node->child, "value", NULL);
7584 if (!value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007585 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
PavolVican99c70722017-02-18 17:25:52 +01007586 return EXIT_FAILURE;
7587 }
7588 if (ly_strequal(value, "true", 0)) {
7589 ((uint8_t *)str)[c] = 1;
7590 } else if (ly_strequal(value, "false", 0)) {
7591 ((uint8_t *)str)[c] = 2;
7592 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007593 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
PavolVican99c70722017-02-18 17:25:52 +01007594 return EXIT_FAILURE;
7595 }
7596
7597 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7598 return EXIT_FAILURE;
7599 }
7600 }
7601 }
Radek Krejci56c80412017-02-09 10:44:16 +01007602 }
7603 }
7604 if (p) {
7605 /* enlarge the array(s) */
7606 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7607 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007608 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007609 lydict_remove(mod->ctx, p[0][c]);
7610 p[0][c] = NULL;
7611 return EXIT_FAILURE;
7612 }
7613 p[0] = reallocated;
7614 p[0][c + 1] = NULL;
7615
7616 if (stmt == LY_STMT_BELONGSTO) {
7617 /* enlarge the second belongs-to's array with prefixes */
7618 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7619 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007620 LOGMEM(mod->ctx);
Radek Krejci56c80412017-02-09 10:44:16 +01007621 lydict_remove(mod->ctx, p[1][c]);
7622 p[1][c] = NULL;
7623 return EXIT_FAILURE;
7624 }
7625 p[1] = reallocated;
7626 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007627 } else if (stmt == LY_STMT_ARGUMENT){
7628 /* enlarge the second argument's array with yin element */
7629 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7630 if (!reallocated) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007631 LOGMEM(mod->ctx);
PavolVican99c70722017-02-18 17:25:52 +01007632 ((uint8_t *)p[1])[c] = 0;
7633 return EXIT_FAILURE;
7634 }
7635 p[1] = reallocated;
7636 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007637 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007638 }
7639
7640 return EXIT_SUCCESS;
7641}
7642
7643static void *
7644yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7645 uint16_t mask)
7646{
7647 void *data;
7648 struct lyext_substmt *info;
7649
7650 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7651 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007652 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007653 return NULL;
7654 }
7655 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007656 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007657 return NULL;
7658 }
7659
7660 return data;
7661}
7662
Radek Krejcic1885952017-02-07 09:37:51 +01007663static int
7664yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007665 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007666 const char *val1_str, const char *val2_str, uint16_t mask,
7667 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7668{
7669 uint16_t *val;
7670 const char *str;
7671
7672 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7673 if (!val) {
7674 return EXIT_FAILURE;
7675 }
7676
7677 str = lyxml_get_attr(node, "value", NULL);
7678 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007679 LOGVAL(mod->ctx, LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007680 } else if (!strcmp(val1_str, str)) {
7681 *val = *val | val1;
7682 } else if (!strcmp(val2_str, str)) {
7683 *val = *val | val2;
7684 } else {
7685 /* unknown value */
Michal Vasko53b7da02018-02-13 15:28:42 +01007686 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
Radek Krejcic1885952017-02-07 09:37:51 +01007687 return EXIT_FAILURE;
7688 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007689 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007690 return EXIT_FAILURE;
7691 }
7692 return EXIT_SUCCESS;
7693}
7694
Radek Krejcif95b6292017-02-13 15:57:37 +01007695static struct lys_node **
7696yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7697{
7698 struct lyext_substmt *info;
7699 struct lys_node **snode, *siter;
7700
7701 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7702 if (!snode) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007703 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007704 return NULL;
7705 }
7706 if (info->cardinality < LY_STMT_CARD_SOME) {
7707 LY_TREE_FOR(*snode, siter) {
7708 if (stmt == lys_snode2stmt(siter->nodetype)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007709 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejcif95b6292017-02-13 15:57:37 +01007710 return NULL;
7711 }
7712 }
7713 }
7714
7715 return snode;
7716}
7717
Radek Krejci8d6b7422017-02-03 14:42:13 +01007718static void **
7719yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7720{
7721 int c;
7722 void **data, ***p = NULL;
7723 void *reallocated;
7724 struct lyext_substmt *info;
7725
7726 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7727 if (!data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007728 LOGVAL(ext->module->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007729 return NULL;
7730 }
7731 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007732 LOGVAL(ext->module->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007733 return NULL;
7734 }
7735
7736 c = 0;
7737 if (info->cardinality >= LY_STMT_CARD_SOME) {
7738 /* there can be multiple instances, so instead of pointer to array,
7739 * we have in data pointer to pointer to array */
7740 p = (void ***)data;
7741 data = *p;
7742 if (!data) {
7743 /* allocate initial array */
7744 *p = data = malloc(2 * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007745 LY_CHECK_ERR_RETURN(!data, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007746 } else {
7747 for (c = 0; *data; data++, c++);
7748 }
7749 }
7750
7751 if (p) {
7752 /* enlarge the array */
7753 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Michal Vasko53b7da02018-02-13 15:28:42 +01007754 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ext->module->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007755 *p = reallocated;
7756 data = *p;
7757 data[c + 1] = NULL;
7758 }
7759
7760 return &data[c];
7761}
7762
7763int
7764lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7765 struct unres_schema *unres)
7766{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007767 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007768 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007769 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007770 const char *value, *name;
7771 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007772 struct lyext_substmt *info;
7773 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007774 long long int ll;
7775 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007776 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007777
Radek Krejcia8d111f2017-05-31 13:57:37 +02007778#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7779 *(TYPE **)TO = malloc(sizeof(TYPE)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007780 if (!*(TYPE **)TO) { LOGMEM(mod->ctx); goto error; } \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007781 (**(TYPE **)TO) = (TYPE)FROM;
7782
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007783#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007784 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7785 if (!p) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007786 LOGVAL(mod->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007787 goto error; \
7788 } \
7789 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
Michal Vasko53b7da02018-02-13 15:28:42 +01007790 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007791 goto error; \
7792 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007793 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007794 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7795 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007796 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007797 if (!(*pp)) { \
7798 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Michal Vasko53b7da02018-02-13 15:28:42 +01007799 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007800 } else { \
7801 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7802 } \
7803 p = &(*(TYPE**)pp)[i]; \
7804 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007805#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007806 if (pp) { \
7807 /* enlarge the array */ \
7808 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007809 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(mod->ctx), error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007810 *pp = reallocated; \
7811 (*(TYPE**)pp)[i + 1] = 0; \
7812 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007813#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7814 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7815 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007816 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007817#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7818 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007819 GETVAL(mod->ctx, value, node, "value"); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007820 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Michal Vasko53b7da02018-02-13 15:28:42 +01007821 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007822 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7823 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7824 goto error; \
7825 } \
7826 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007827
Radek Krejci8d6b7422017-02-03 14:42:13 +01007828 LY_TREE_FOR_SAFE(yin->child, next, node) {
7829 if (!node->ns) {
7830 /* garbage */
7831 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7832 /* we have the extension's argument */
7833 if (ext->arg_value) {
Michal Vasko53b7da02018-02-13 15:28:42 +01007834 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007835 goto error;
7836 }
7837 ext->arg_value = node->content;
7838 node->content = NULL;
7839 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7840 /* extension */
7841 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7842 goto error;
7843 }
7844 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007845 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007846 goto error;
7847 }
7848 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007849 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007850 goto error;
7851 }
7852 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007853 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007854 goto error;
7855 }
7856 } else if (!strcmp(node->name, "type")) {
7857 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7858 if (!type) {
7859 goto error;
7860 }
7861 /* allocate type structure */
7862 (*type) = calloc(1, sizeof **type);
Michal Vasko53b7da02018-02-13 15:28:42 +01007863 LY_CHECK_ERR_GOTO(!*type, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007864
7865 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007866 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007867 (*type)->der = (struct lys_tpdf *)node;
7868 (*type)->parent = (struct lys_tpdf *)ext;
7869
7870 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7871 (*type)->der = NULL;
7872 goto error;
7873 }
7874 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007875 } else if (!strcmp(node->name, "typedef")) {
7876 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7877 if (!pp) {
7878 goto error;
7879 }
7880 /* allocate typedef structure */
7881 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Michal Vasko53b7da02018-02-13 15:28:42 +01007882 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007883
7884 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7885 goto error;
7886 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007887 } else if (!strcmp(node->name, "if-feature")) {
7888 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7889 if (!pp) {
7890 goto error;
7891 }
7892 /* allocate iffeature structure */
7893 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Michal Vasko53b7da02018-02-13 15:28:42 +01007894 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007895
7896 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7897 goto error;
7898 }
7899 } else if (!strcmp(node->name, "status")) {
7900 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7901 if (!p) {
7902 goto error;
7903 }
7904
Michal Vasko53b7da02018-02-13 15:28:42 +01007905 GETVAL(mod->ctx, value, node, "value");
Radek Krejci8d6b7422017-02-03 14:42:13 +01007906 if (!strcmp(value, "current")) {
7907 *(uint16_t*)p |= LYS_STATUS_CURR;
7908 } else if (!strcmp(value, "deprecated")) {
7909 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7910 } else if (!strcmp(value, "obsolete")) {
7911 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7912 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01007913 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007914 goto error;
7915 }
7916
7917 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7918 goto error;
7919 }
Radek Krejcic1885952017-02-07 09:37:51 +01007920 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007921 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Michal Vasko53b7da02018-02-13 15:28:42 +01007922 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007923 goto error;
7924 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007925 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007926 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007927 goto error;
7928 }
7929 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007930 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007931 goto error;
7932 }
Radek Krejcic1885952017-02-07 09:37:51 +01007933 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007934 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007935 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7936 goto error;
7937 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007938 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007939 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007940 goto error;
7941 }
7942 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007943 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007944 goto error;
7945 }
7946 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007947 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007948 goto error;
7949 }
7950 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007951 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007952 goto error;
7953 }
7954 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007955 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007956 goto error;
7957 }
7958 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007959 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007960 goto error;
7961 }
7962 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007963 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007964 goto error;
7965 }
7966 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007967 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007968 goto error;
7969 }
Radek Krejcic1885952017-02-07 09:37:51 +01007970 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007971 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7972 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007973 goto error;
7974 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007975 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007976 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007977 goto error;
7978 }
7979 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007980 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007981 goto error;
7982 }
7983 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007984 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007985 goto error;
7986 }
7987 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007988 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007989 goto error;
7990 }
Radek Krejcic1885952017-02-07 09:37:51 +01007991 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007992 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007993 goto error;
7994 }
7995 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007996 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007997 goto error;
7998 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007999 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008000 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008001
Michal Vasko53b7da02018-02-13 15:28:42 +01008002 GETVAL(mod->ctx, value, node, "value");
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008003 v = strtol(value, NULL, 10);
8004
8005 /* range check */
8006 if (v < 1 || v > 18) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008007 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008008 goto error;
8009 }
8010
8011 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
8012 goto error;
8013 }
8014
8015 /* store the value */
8016 (*(uint8_t *)p) = (uint8_t)v;
8017
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008018 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01008019 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008020 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008021
Michal Vasko53b7da02018-02-13 15:28:42 +01008022 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008023 while (isspace(value[0])) {
8024 value++;
8025 }
8026
8027 if (!strcmp(value, "unbounded")) {
8028 u = 0;
8029 } else {
8030 /* convert it to uint32_t */
8031 errno = 0; endptr = NULL;
8032 u = strtoul(value, &endptr, 10);
8033 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008034 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008035 goto error;
8036 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01008037 }
Radek Krejci5496fae2017-02-10 13:26:48 +01008038
8039 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8040 goto error;
8041 }
8042
8043 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008044 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008045
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008046 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008047 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008048 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008049
Michal Vasko53b7da02018-02-13 15:28:42 +01008050 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008051 while (isspace(value[0])) {
8052 value++;
8053 }
8054
8055 /* convert it to uint32_t */
8056 errno = 0;
8057 endptr = NULL;
8058 u = strtoul(value, &endptr, 10);
8059 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008060 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008061 goto error;
8062 }
8063
8064 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8065 goto error;
8066 }
8067
8068 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008069 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008070
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008071 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008072 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008073 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8074
Michal Vasko53b7da02018-02-13 15:28:42 +01008075 GETVAL(mod->ctx, value, node, "value");
PavolVican2ed9f4e2017-02-16 00:08:45 +01008076 while (isspace(value[0])) {
8077 value++;
8078 }
8079
8080 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008081 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008082
8083 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008084 if (ll < INT32_MIN || ll > INT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008085 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008086 goto error;
8087 }
8088
8089 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8090 goto error;
8091 }
8092
8093 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008094 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01008095
8096 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008097 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008098 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008099
Michal Vasko53b7da02018-02-13 15:28:42 +01008100 GETVAL(mod->ctx, value, node, "value");
Radek Krejci5496fae2017-02-10 13:26:48 +01008101 ll = strtoll(value, NULL, 10);
8102
8103 /* range check */
8104 if (ll < 0 || ll > UINT32_MAX) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008105 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci5496fae2017-02-10 13:26:48 +01008106 goto error;
8107 }
8108
8109 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8110 goto error;
8111 }
8112
8113 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02008114 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01008115
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008116 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008117 } else if (!strcmp(node->name, "module")) {
8118 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8119 if (!pp) {
8120 goto error;
8121 }
8122
8123 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8124 if (!(*pp)) {
8125 goto error;
8126 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008127 } else if (!strcmp(node->name, "when")) {
8128 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8129
8130 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8131 if (!*(struct lys_when**)p) {
8132 goto error;
8133 }
8134
8135 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008136 } else if (!strcmp(node->name, "revision")) {
8137 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8138
8139 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Michal Vasko53b7da02018-02-13 15:28:42 +01008140 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM(mod->ctx), error);
Radek Krejci7417a082017-02-16 11:07:59 +01008141 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8142 goto error;
8143 }
8144
8145 /* check uniqueness of the revision dates - not required by RFC */
8146 if (pp) {
8147 for (j = 0; j < i; j++) {
8148 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008149 LOGWRN(mod->ctx, "Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
Radek Krejci7417a082017-02-16 11:07:59 +01008150 }
8151 }
8152 }
8153
8154 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008155 } else if (!strcmp(node->name, "unique")) {
8156 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8157
8158 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Michal Vasko53b7da02018-02-13 15:28:42 +01008159 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM(mod->ctx), error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008160 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8161 goto error;
8162 }
8163
8164 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8165 goto error;
8166 }
8167 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008168 } else if (!strcmp(node->name, "action")) {
8169 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8170 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008171 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008172 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008173 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008174 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008175 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008176 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008177 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008178 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008179 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008180 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008181 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008182 } else if (!strcmp(node->name, "output")) {
8183 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8184 } else if (!strcmp(node->name, "input")) {
8185 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8186 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008187 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008188 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008189 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008190 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008191 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008192 } else if (!strcmp(node->name, "notification")) {
8193 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8194 } else if (!strcmp(node->name, "uses")) {
8195 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008196 } else if (!strcmp(node->name, "length")) {
8197 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8198 } else if (!strcmp(node->name, "must")) {
8199 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8200 if (!pp) {
8201 goto error;
8202 }
8203 /* allocate structure for must */
8204 (*pp) = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008205 LY_CHECK_ERR_GOTO(!*pp, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008206
8207 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8208 goto error;
8209 }
8210 } else if (!strcmp(node->name, "pattern")) {
8211 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
Michal Vasko53b7da02018-02-13 15:28:42 +01008212 GETVAL(mod->ctx, value, node, "value");
8213 if (lyp_check_pattern(mod->ctx, value, NULL)) {
Radek Krejciaa9c5202017-02-15 16:10:14 +01008214 goto error;
8215 }
8216
8217 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Michal Vasko53b7da02018-02-13 15:28:42 +01008218 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008219
8220 modifier = 0x06; /* ACK */
8221 if (mod->version >= 2) {
8222 name = NULL;
8223 LY_TREE_FOR(node->child, child) {
8224 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8225 if (name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01008226 LOGVAL(mod->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008227 goto error;
8228 }
8229
Michal Vasko53b7da02018-02-13 15:28:42 +01008230 GETVAL(mod->ctx, name, child, "value");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008231 if (!strcmp(name, "invert-match")) {
8232 modifier = 0x15; /* NACK */
8233 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008234 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
Radek Krejciaa9c5202017-02-15 16:10:14 +01008235 goto error;
8236 }
8237 /* get extensions of the modifier */
8238 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8239 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8240 goto error;
8241 }
8242 }
8243 }
8244 }
8245
8246 /* store the value: modifier byte + value + terminating NULL byte */
8247 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Michal Vasko53b7da02018-02-13 15:28:42 +01008248 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM(mod->ctx), error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008249 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8250 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8251 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8252
8253 /* get possible sub-statements */
8254 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8255 goto error;
8256 }
8257
8258 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8259 } else if (!strcmp(node->name, "range")) {
8260 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008261 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01008262 LOGERR(mod->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008263 }
8264 lyxml_free(mod->ctx, node);
8265 }
8266
PavolVicanc4b798e2017-02-20 23:15:27 +01008267 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8268 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008269 }
8270
Radek Krejci8d6b7422017-02-03 14:42:13 +01008271 return EXIT_SUCCESS;
8272
8273error:
8274 return EXIT_FAILURE;
8275}