blob: be62aede0320419240fd94a13a8c9072f88eb62d [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 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
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>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020024#include <pcre.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025
Radek Krejci998a0b82015-08-17 13:14:36 +020026#include "libyang.h"
27#include "common.h"
28#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020029#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020030#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020032#include "resolve.h"
33#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020034#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020035
Radek Krejciadb57612016-02-16 13:34:34 +010036#define GETVAL(value, node, arg) \
37 value = lyxml_get_attr(node, arg, NULL); \
38 if (!value) { \
Michal Vaskoe5e06292016-02-26 09:56:41 +010039 LOGVAL(LYE_MISSARG, LOGLINE(node), LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010040 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010041 }
Radek Krejcice7fb782015-05-29 16:52:34 +020042
Radek Krejcic6556022016-01-27 15:16:45 +010043/* parser.c */
44int dup_prefix_check(const char *prefix, struct lys_module *module);
45
Radek Krejcib388c152015-06-04 17:03:03 +020046#define OPT_IDENT 0x01
47#define OPT_CONFIG 0x02
48#define OPT_MODULE 0x04
49#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020050#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020051static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020052
Radek Krejcib8048692015-08-05 13:36:34 +020053static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020054 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020055static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020056 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020057static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020058 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020059static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020060 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020061static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020062 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020063static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020064 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020065static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020066 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020067static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020068 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020069static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020070 int resolve, struct unres_schema *unres);
71static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020072
Michal Vasko0d343d12015-08-24 14:57:36 +020073/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020074static const char *
75read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020076{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020077 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 /* there should be <text> child */
80 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010081 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Michal Vaskoe5e06292016-02-26 09:56:41 +010082 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010083 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084 } else if (node->child->content) {
85 len = strlen(node->child->content);
86 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010087 } else {
88 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020090}
91
Michal Vasko0d343d12015-08-24 14:57:36 +020092/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093static int
Michal Vasko1d337e12016-02-15 12:32:04 +010094fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
95{
96 int r;
97 const char *value;
98
99 GETVAL(value, yin, "name");
100 if (!(value = transform_schema2json(parent->module, value, LOGLINE(yin)))) {
101 return EXIT_FAILURE;
102 }
103
104 /* HACK - store pointer to the parent node for later status check */
105 *iffeat = (struct lys_feature *)parent;
106 r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value,
107 LOGLINE(yin));
108 lydict_remove(parent->module->ctx, value);
109 if (!r) {
110 return EXIT_SUCCESS;
111 }
112
113error:
114 return EXIT_FAILURE;
115}
116
117/* logs directly */
118static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200119fill_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 +0200120{
Radek Krejci73adb602015-07-02 18:07:40 +0200121 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200122 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100123 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200124
Michal Vasko4cfcd252015-08-03 14:31:10 +0200125 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100126 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200127
Radek Krejci76512572015-08-04 09:47:08 +0200128 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200129 return EXIT_FAILURE;
130 }
Radek Krejci04581c62015-05-22 21:24:00 +0200131
Radek Krejci73adb602015-07-02 18:07:40 +0200132 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200133 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
134 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200135 continue;
136 }
137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200138 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100139 if (base_flag) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100140 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200141 return EXIT_FAILURE;
142 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100143 base_flag = 1;
144
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200145 GETVAL(value, node, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100146 value = transform_schema2json(module, value, LOGLINE(node));
147 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200148 return EXIT_FAILURE;
149 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100150
151 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
152 lydict_remove(module->ctx, value);
153 return EXIT_FAILURE;
154 }
155 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200156 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100157 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200158 return EXIT_FAILURE;
159 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200160 }
Radek Krejci04581c62015-05-22 21:24:00 +0200161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200162 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200163
164error:
165 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200166}
167
Michal Vasko0d343d12015-08-24 14:57:36 +0200168/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200169static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200170read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200171{
Radek Krejci73adb602015-07-02 18:07:40 +0200172 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200173 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200174
Radek Krejci73adb602015-07-02 18:07:40 +0200175 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200176 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
177 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200178 continue;
179 }
180
Radek Krejci41726f92015-06-19 13:11:05 +0200181 if (!strcmp(child->name, "description")) {
182 if (restr->dsc) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100183 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200184 return EXIT_FAILURE;
185 }
186 restr->dsc = read_yin_subnode(ctx, child, "text");
187 if (!restr->dsc) {
188 return EXIT_FAILURE;
189 }
190 } else if (!strcmp(child->name, "reference")) {
191 if (restr->ref) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100192 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200193 return EXIT_FAILURE;
194 }
195 restr->ref = read_yin_subnode(ctx, child, "text");
196 if (!restr->ref) {
197 return EXIT_FAILURE;
198 }
199 } else if (!strcmp(child->name, "error-app-tag")) {
200 if (restr->eapptag) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100201 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200202 return EXIT_FAILURE;
203 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200204 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200205 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200206 } else if (!strcmp(child->name, "error-message")) {
207 if (restr->emsg) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100208 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200209 return EXIT_FAILURE;
210 }
211 restr->emsg = read_yin_subnode(ctx, child, "value");
212 if (!restr->emsg) {
213 return EXIT_FAILURE;
214 }
215 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100216 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200217 return EXIT_FAILURE;
218 }
Radek Krejci41726f92015-06-19 13:11:05 +0200219 }
220
221 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200222
223error:
224 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200225}
226
Michal Vasko88c29542015-11-27 14:57:53 +0100227/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
228int
Radek Krejcib8048692015-08-05 13:36:34 +0200229fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Michal Vaskof02e3742015-08-05 16:27:02 +0200230 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200231{
Michal Vasko1dca6882015-10-22 14:29:42 +0200232 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200233 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200234 struct lys_restr **restr;
235 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200236 pcre *precomp;
237 int i, j, rc, err_offset;
Radek Krejcidc008d72016-02-17 13:12:14 +0100238 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200239 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200240 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200241
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200242 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200243 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200244 if (!value) {
245 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200246 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200247
248 i = parse_identifier(value);
249 if (i < 1) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100250 LOGVAL(LYE_INCHAR, LOGLINE(yin), LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100251 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200252 goto error;
253 }
254 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100255 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200256 if (value[i]) {
257 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100258 name += i;
259 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100260 LOGVAL(LYE_INCHAR, LOGLINE(yin), LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100261 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200262 goto error;
263 }
Radek Krejci225376f2016-02-16 17:36:22 +0100264 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200265 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200266
Radek Krejci225376f2016-02-16 17:36:22 +0100267 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100268 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200269 if (rc == -1) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100270 LOGVAL(LYE_INMOD, LOGLINE(yin), LY_VLOG_NONE, NULL, type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200271 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100272
273 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200274 } else if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100275 ret = EXIT_FAILURE;
276 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200277 }
278 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200279
Radek Krejcicf509982015-12-15 09:22:44 +0100280 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100281 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejciadb57612016-02-16 13:34:34 +0100282 type->der->flags, type->der->module, type->der->name, LOGLINE(yin), parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100283 return -1;
284 }
285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200286 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200287 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200288 /* RFC 6020 9.7.4 - bit */
289
290 /* get bit specifications, at least one must be present */
291 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200292 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
293 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100294 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200295 continue;
296 }
297
Radek Krejci994b6f62015-06-18 16:47:27 +0200298 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200299 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200300 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100301 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200302 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200303 }
304 }
Radek Krejciac781922015-07-09 15:35:14 +0200305 if (!type->der->type.der && !type->info.bits.count) {
306 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe5e06292016-02-26 09:56:41 +0100307 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200308 goto error;
309 }
Radek Krejciac781922015-07-09 15:35:14 +0200310 if (type->der->type.der && type->info.bits.count) {
311 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe5e06292016-02-26 09:56:41 +0100312 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200313 goto error;
314 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200315
316 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100317 if (!type->info.bits.bit) {
318 LOGMEM;
319 goto error;
320 }
Radek Krejci73adb602015-07-02 18:07:40 +0200321 p = 0;
322 i = -1;
323 LY_TREE_FOR(yin->child, next) {
324 i++;
325
326 GETVAL(value, next, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100327 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100328 LOGVAL(LYE_PATH, 0, LY_VLOG_NONE, NULL);
Michal Vasko2d26a022015-12-07 09:27:21 +0100329 goto error;
330 }
331
Radek Krejci994b6f62015-06-18 16:47:27 +0200332 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200333 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200334 type->info.bits.count = i + 1;
335 goto error;
336 }
337
338 /* check the name uniqueness */
339 for (j = 0; j < i; j++) {
340 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100341 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200342 type->info.bits.count = i + 1;
343 goto error;
344 }
345 }
346
Radek Krejci0d70c372015-07-02 16:23:10 +0200347 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200348 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200349 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
350 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200351 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200352 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200353
Radek Krejci0d70c372015-07-02 16:23:10 +0200354 if (!strcmp(node->name, "position")) {
355 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200356 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200357
358 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200359 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100360 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200361 type->info.bits.count = i + 1;
362 goto error;
363 }
364 type->info.bits.bit[i].pos = (uint32_t)p_;
365
366 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200367 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200368 p = type->info.bits.bit[i].pos;
369 p++;
370 } else {
371 /* check that the value is unique */
372 for (j = 0; j < i; j++) {
373 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100374 LOGVAL(LYE_BITS_DUPVAL, LOGLINE(node), LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100375 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200376 type->info.bits.count = i + 1;
377 goto error;
378 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200379 }
380 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200381 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100382 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200383 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200384 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200385 }
386 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200387 /* assign value automatically */
388 if (p > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100389 LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200390 type->info.bits.count = i + 1;
391 goto error;
392 }
393 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100394 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200395 p++;
396 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200397
398 /* keep them ordered by position */
399 j = i;
400 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
401 /* switch them */
402 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
403 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
404 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
405 j--;
406 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200408 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200410 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200411 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200412 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200413 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
414 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200415 continue;
416 }
417
Radek Krejcif9401c32015-06-26 16:47:36 +0200418 if (!strcmp(node->name, "range")) {
419 if (type->info.dec64.range) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100420 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200421 goto error;
422 }
423
424 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200425 if (lyp_check_length_range(value, type)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100426 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200427 goto error;
428 }
429 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100430 if (!type->info.dec64.range) {
431 LOGMEM;
432 goto error;
433 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200434 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
435
436 /* get possible substatements */
437 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
438 goto error;
439 }
440 } else if (!strcmp(node->name, "fraction-digits")) {
441 if (type->info.dec64.dig) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100442 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200443 goto error;
444 }
445 GETVAL(value, node, "value");
446 v = strtol(value, NULL, 10);
447
448 /* range check */
449 if (v < 1 || v > 18) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100450 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200451 goto error;
452 }
453 type->info.dec64.dig = (uint8_t)v;
454 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100455 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200456 goto error;
457 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200458 }
459
460 /* mandatory sub-statement(s) check */
461 if (!type->info.dec64.dig && !type->der->type.der) {
462 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe5e06292016-02-26 09:56:41 +0100463 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200464 goto error;
465 }
Radek Krejci7511f402015-07-10 09:56:30 +0200466 if (type->info.dec64.dig && type->der->type.der) {
467 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe5e06292016-02-26 09:56:41 +0100468 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200469 goto error;
470 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200471 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200473 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200474 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200475
Radek Krejci994b6f62015-06-18 16:47:27 +0200476 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200478 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
479 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100480 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200481 continue;
482 }
483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200485 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200486 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100487 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200488 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 }
490 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200491 if (!type->der->type.der && !type->info.enums.count) {
492 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe5e06292016-02-26 09:56:41 +0100493 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494 goto error;
495 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200496 if (type->der->type.der && type->info.enums.count) {
497 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe5e06292016-02-26 09:56:41 +0100498 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200499 goto error;
500 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200501
Radek Krejci1574a8d2015-08-03 14:16:52 +0200502 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100503 if (!type->info.enums.enm) {
504 LOGMEM;
505 goto error;
506 }
Radek Krejci73adb602015-07-02 18:07:40 +0200507 v = 0;
508 i = -1;
509 LY_TREE_FOR(yin->child, next) {
510 i++;
511
512 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100513 if (!value[0]) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100514 LOGVAL(LYE_SPEC, LOGLINE(next), LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100515 goto error;
516 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200517 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200518 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200519 type->info.enums.count = i + 1;
520 goto error;
521 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200523 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200524 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100526 LOGVAL(LYE_ENUM_WS, LOGLINE(next), LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200527 type->info.enums.count = i + 1;
528 goto error;
529 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200531 /* check the name uniqueness */
532 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200533 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100534 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200535 type->info.enums.count = i + 1;
536 goto error;
537 }
538 }
Radek Krejci04581c62015-05-22 21:24:00 +0200539
Radek Krejci0d70c372015-07-02 16:23:10 +0200540 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200541 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200542 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
543 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200544 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200545 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200546
Radek Krejci0d70c372015-07-02 16:23:10 +0200547 if (!strcmp(node->name, "value")) {
548 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200549 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200550
551 /* range check */
552 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100553 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200554 type->info.enums.count = i + 1;
555 goto error;
556 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200557 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200558
559 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200560 if (type->info.enums.enm[i].value > v) {
561 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200562 v++;
563 } else {
564 /* check that the value is unique */
565 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200566 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100567 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100568 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200569 type->info.enums.count = i + 1;
570 goto error;
571 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200572 }
573 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200574 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100575 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200576 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200577 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200578 }
579 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200580 /* assign value automatically */
581 if (v > INT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100582 LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 type->info.enums.count = i + 1;
584 goto error;
585 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200586 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100587 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200588 v++;
589 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 }
591 break;
592
593 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200594 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595
596 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200597 LY_TREE_FOR_SAFE(yin->child, next, node) {
598 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
599 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100600 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200601 continue;
602 }
603
Michal Vaskoe29c6622015-11-27 15:02:31 +0100604 if (strcmp(node->name, "base")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100605 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200606 goto error;
607 }
608 }
609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200610 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200611 if (type->der->type.der) {
612 /* this is just a derived type with no base specified/required */
613 break;
614 }
Michal Vaskoe5e06292016-02-26 09:56:41 +0100615 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200616 goto error;
617 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 if (yin->child->next) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100619 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100620 yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 goto error;
622 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200623 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100624 /* store in the JSON format */
625 value = transform_schema2json(module, value, LOGLINE(yin->child));
626 if (!value) {
627 goto error;
628 }
Radek Krejcic5989d42016-02-17 11:16:38 +0100629 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child));
630 lydict_remove(module->ctx, value);
631
632 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200633 goto error;
634 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 break;
636
637 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200638 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200639 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200640 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
641 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200642 continue;
643 }
644
Radek Krejciaf351422015-06-19 14:49:38 +0200645 if (!strcmp(node->name, "require-instance")) {
646 if (type->info.inst.req) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100647 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200648 goto error;
649 }
650 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200651 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200652 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200653 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200654 type->info.inst.req = -1;
655 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100656 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200657 goto error;
658 }
659 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100660 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200661 goto error;
662 }
Radek Krejciaf351422015-06-19 14:49:38 +0200663 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200665 break;
666
Radek Krejcif2860132015-06-20 12:37:20 +0200667 case LY_TYPE_BINARY:
668 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200669 case LY_TYPE_INT8:
670 case LY_TYPE_INT16:
671 case LY_TYPE_INT32:
672 case LY_TYPE_INT64:
673 case LY_TYPE_UINT8:
674 case LY_TYPE_UINT16:
675 case LY_TYPE_UINT32:
676 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200677 /* RFC 6020 9.2.4 - range */
678
679 /* length and range are actually the same restriction, so process
680 * them by this common code, we just need to differ the name and
681 * structure where the information will be stored
682 */
683 if (type->base == LY_TYPE_BINARY) {
684 restr = &type->info.binary.length;
685 name = "length";
686 } else {
687 restr = &type->info.num.range;
688 name = "range";
689 }
690
Radek Krejci73adb602015-07-02 18:07:40 +0200691 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200692 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
693 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200694 continue;
695 }
696
Radek Krejcif2860132015-06-20 12:37:20 +0200697 if (!strcmp(node->name, name)) {
698 if (*restr) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100699 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200700 goto error;
701 }
702
703 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200704 if (lyp_check_length_range(value, type)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100705 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200706 goto error;
707 }
708 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100709 if (!(*restr)) {
710 LOGMEM;
711 goto error;
712 }
Radek Krejcif2860132015-06-20 12:37:20 +0200713 (*restr)->expr = lydict_insert(module->ctx, value, 0);
714
715 /* get possible substatements */
716 if (read_restr_substmt(module->ctx, *restr, node)) {
717 goto error;
718 }
719 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100720 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200721 goto error;
722 }
Radek Krejcif2860132015-06-20 12:37:20 +0200723 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200724 break;
725
726 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200727 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200728 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200729 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
730 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200731 continue;
732 }
733
Michal Vasko88c29542015-11-27 14:57:53 +0100734 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200735 if (type->info.lref.path) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100736 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200737 goto error;
738 }
739
740 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200741 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200742 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200743 if (!type->info.lref.path) {
744 goto error;
745 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200746 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200747 goto error;
748 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200749
Radek Krejcidc4c1412015-06-19 15:39:54 +0200750 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100751 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200752 goto error;
753 }
Radek Krejci73adb602015-07-02 18:07:40 +0200754 }
755
Michal Vasko88c29542015-11-27 14:57:53 +0100756 if (!type->info.lref.path && !type->der->type.der) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100757 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200758 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200759 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200760 break;
761
762 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200763 /* RFC 6020 9.4.4 - length */
764 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200765 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200766 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200767 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
768 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100769 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200770 continue;
771 }
772
Radek Krejci3733a802015-06-19 13:43:21 +0200773 if (!strcmp(node->name, "length")) {
774 if (type->info.str.length) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100775 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200776 goto error;
777 }
778
779 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200780 if (lyp_check_length_range(value, type)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100781 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200782 goto error;
783 }
784 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100785 if (!type->info.str.length) {
786 LOGMEM;
787 goto error;
788 }
Radek Krejci3733a802015-06-19 13:43:21 +0200789 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
790
Radek Krejci5fbc9162015-06-19 14:11:11 +0200791 /* get possible sub-statements */
792 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200793 goto error;
794 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100795 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200796 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200797 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200798 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100799 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200800 goto error;
801 }
802 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200803 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200804 if (i) {
805 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100806 if (!type->info.str.patterns) {
807 LOGMEM;
808 goto error;
809 }
Radek Krejci73adb602015-07-02 18:07:40 +0200810 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100811 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200812
813 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200814 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
815 if (!precomp) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100816 LOGVAL(LYE_INREGEX, LOGLINE(node), LY_VLOG_NONE, NULL, value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200817 free(type->info.str.patterns);
818 goto error;
819 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200820 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200821
Radek Krejci73adb602015-07-02 18:07:40 +0200822 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200823
824 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100825 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200826 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200827 goto error;
828 }
Radek Krejci73adb602015-07-02 18:07:40 +0200829 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200830 }
831 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200832 break;
833
834 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200835 /* RFC 6020 7.4 - type */
836 /* count number of types in union */
837 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200838 LY_TREE_FOR_SAFE(yin->child, next, node) {
839 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
840 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100841 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200842 continue;
843 }
844
Radek Krejcie4c366b2015-07-02 10:11:31 +0200845 if (!strcmp(node->name, "type")) {
846 i++;
847 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100848 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200849 goto error;
850 }
851 }
852
853 if (!i) {
854 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100855 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200856 break;
857 }
Michal Vaskoe5e06292016-02-26 09:56:41 +0100858 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200859 goto error;
860 }
861
862 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200863 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100864 if (!type->info.uni.types) {
865 LOGMEM;
866 goto error;
867 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200868 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200869 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100870 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100871 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
872 if (!rc) {
873 type->info.uni.count++;
874
875 /* union's type cannot be empty or leafref */
876 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100877 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100878 rc = -1;
879 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100880 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100881 rc = -1;
882 }
883 }
884 if (rc) {
885 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
886 for (i = 0; i < type->info.uni.count; ++i) {
887 lys_type_free(module->ctx, &type->info.uni.types[i]);
888 }
889 free(type->info.uni.types);
890 type->info.uni.types = NULL;
891 type->info.uni.count = 0;
892
893 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100894 ret = EXIT_FAILURE;
895 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100896 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200897 goto error;
898 }
Michal Vasko88c29542015-11-27 14:57:53 +0100899 }
900 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200901
Michal Vasko88c29542015-11-27 14:57:53 +0100902 case LY_TYPE_BOOL:
903 case LY_TYPE_EMPTY:
904 /* no sub-statement allowed */
905 LY_TREE_FOR(yin->child, node) {
906 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100907 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200908 goto error;
909 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 break;
912
913 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100914 LOGINT;
915 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916 }
917
918 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200919
920error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100921 if (type->module_name) {
922 lydict_remove(module->ctx, type->module_name);
923 type->module_name = NULL;
924 }
925 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200926}
927
Michal Vasko0d343d12015-08-24 14:57:36 +0200928/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200929static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200930fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200931{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100933 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200934 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100937 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 goto error;
939 }
940 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100943 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 goto error;
945 }
Radek Krejcieac35532015-05-31 19:09:15 +0200946
Michal Vasko88c29542015-11-27 14:57:53 +0100947 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200948 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
949 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200950 continue;
951 }
952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100954 if (has_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100955 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200956 goto error;
957 }
Michal Vasko88c29542015-11-27 14:57:53 +0100958 /* HACK for unres */
959 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100960 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100961 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200962 goto error;
963 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200964 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 } else if (!strcmp(node->name, "default")) {
966 if (tpdf->dflt) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100967 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200968 goto error;
969 }
970 GETVAL(value, node, "value");
971 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200972 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 } else if (!strcmp(node->name, "units")) {
974 if (tpdf->units) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100975 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200976 goto error;
977 }
978 GETVAL(value, node, "name");
979 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
980 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100981 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 goto error;
983 }
984 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200986 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200987 if (!has_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +0100988 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 goto error;
990 }
Radek Krejcieac35532015-05-31 19:09:15 +0200991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200993 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +0200994 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200995 goto error;
996 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001000
1001error:
1002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001004}
1005
Michal Vasko0d343d12015-08-24 14:57:36 +02001006/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001007static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001008fill_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 +02001009{
1010 const char *value;
1011 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001012 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001013
Radek Krejcib05774c2015-06-18 13:52:59 +02001014 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01001015 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001016 goto error;
1017 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001018 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001019 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001020
Radek Krejci76512572015-08-04 09:47:08 +02001021 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001022 goto error;
1023 }
1024
1025 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001026 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1027 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001028 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001029 continue;
1030 }
1031
Radek Krejci3cf9e222015-06-18 11:37:50 +02001032 if (!strcmp(child->name, "if-feature")) {
1033 c++;
1034 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001035 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001036 goto error;
1037 }
1038 }
1039
1040 if (c) {
1041 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001042 if (!f->features) {
1043 LOGMEM;
1044 goto error;
1045 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001046 }
Radek Krejci73adb602015-07-02 18:07:40 +02001047 LY_TREE_FOR(yin->child, child) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001048 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001049 f->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001050 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001051 goto error;
1052 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001053 }
1054
Radek Krejci3cf9e222015-06-18 11:37:50 +02001055 return EXIT_SUCCESS;
1056
1057error:
1058
1059 return EXIT_FAILURE;
1060}
1061
Michal Vasko0d343d12015-08-24 14:57:36 +02001062/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063static int
Radek Krejcib8048692015-08-05 13:36:34 +02001064fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001065{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001068 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001069 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001070 if (!must->expr) {
1071 goto error;
1072 }
Michal Vasko77dc5652016-02-15 12:32:42 +01001073 if (lyxp_syntax_check(must->expr, LOGLINE(yin))) {
1074 goto error;
1075 }
Radek Krejci800af702015-06-02 13:46:01 +02001076
Radek Krejci41726f92015-06-19 13:11:05 +02001077 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001078
Michal Vasko77dc5652016-02-15 12:32:42 +01001079error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001081}
1082
Radek Krejci581ce772015-11-10 17:22:40 +01001083static int
Michal Vasko88c29542015-11-27 14:57:53 +01001084fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1085 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001086{
1087 int i, j;
1088 const char *value, *vaux;
1089
1090 /* get unique value (list of leafs supposed to be unique */
1091 GETVAL(value, yin, "tag");
1092
1093 /* count the number of unique leafs in the value */
1094 vaux = value;
1095 while ((vaux = strpbrk(vaux, " \t\n"))) {
1096 unique->expr_size++;
1097 while (isspace(*vaux)) {
1098 vaux++;
1099 }
1100 }
1101 unique->expr_size++;
1102 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001103 if (!unique->expr) {
1104 LOGMEM;
1105 goto error;
1106 }
Radek Krejci581ce772015-11-10 17:22:40 +01001107
1108 for (i = 0; i < unique->expr_size; i++) {
1109 vaux = strpbrk(value, " \t\n");
1110 if (!vaux) {
1111 /* the last token, lydict_insert() will count its size on its own */
1112 vaux = value;
1113 }
1114
1115 /* store token into unique structure */
1116 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1117
1118 /* check that the expression does not repeat */
1119 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001120 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001121 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, unique->expr[i], "unique");
Radek Krejciadb57612016-02-16 13:34:34 +01001122 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001123 goto error;
1124 }
1125 }
1126
1127 /* try to resolve leaf */
1128 if (unres) {
1129 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1130 } else {
1131 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1132 goto error;
1133 }
1134 }
1135
1136 /* move to next token */
1137 value = vaux;
1138 while(isspace(*value)) {
1139 value++;
1140 }
1141 }
1142
1143 return EXIT_SUCCESS;
1144
1145error:
1146 return EXIT_FAILURE;
1147}
1148
Michal Vasko0d343d12015-08-24 14:57:36 +02001149/* logs directly
1150 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001151 * type: 0 - min, 1 - max
1152 */
1153static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001154deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001155{
1156 const char *value;
1157 char *endptr;
1158 unsigned long val;
1159 uint32_t *ui32val;
1160
1161 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001162 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001163 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001164 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001165 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001166 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001167 }
Radek Krejci76512572015-08-04 09:47:08 +02001168 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001169 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001170 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001171 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001172 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001173 }
1174 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001175 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001176 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001177 goto error;
1178 }
1179
1180 GETVAL(value, node, "value");
1181 while (isspace(value[0])) {
1182 value++;
1183 }
1184
Radek Krejci0d7b2472016-02-12 11:11:03 +01001185 if (type && !strcmp(value, "unbounded")) {
1186 d->max = val = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001187 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001188 /* convert it to uint32_t */
1189 errno = 0;
1190 endptr = NULL;
1191 val = strtoul(value, &endptr, 10);
1192 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001193 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001194 goto error;
1195 }
1196 if (type) {
1197 d->max = (uint32_t)val;
1198 } else {
1199 d->min = (uint32_t)val;
1200 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001201 }
1202
1203 if (d->mod == LY_DEVIATE_ADD) {
1204 /* check that there is no current value */
1205 if (*ui32val) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001206 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_NONE, NULL, node->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001207 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001208 goto error;
1209 }
1210 }
1211
1212 if (d->mod == LY_DEVIATE_DEL) {
1213 /* check values */
1214 if ((uint32_t)val != *ui32val) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001215 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001216 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001217 goto error;
1218 }
1219 /* remove current min-elements value of the target */
1220 *ui32val = 0;
1221 } else { /* add (already checked) and replace */
1222 /* set new value specified in deviation */
1223 *ui32val = (uint32_t)val;
1224 }
1225
1226 return EXIT_SUCCESS;
1227
1228error:
1229
1230 return EXIT_FAILURE;
1231}
1232
Michal Vasko0d343d12015-08-24 14:57:36 +02001233/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001234static int
Michal Vasko88c29542015-11-27 14:57:53 +01001235fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1236 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001237{
1238 const char *value, **stritem;
1239 struct lyxml_elem *next, *child, *develem;
1240 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001241 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001242 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001243 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001244 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001245 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001246 struct lys_node_choice *choice = NULL;
1247 struct lys_node_leaf *leaf = NULL;
1248 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001249 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001250 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001251 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001252 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001253
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001254 ctx = module->ctx;
1255
Radek Krejcieb00f512015-07-01 16:44:58 +02001256 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001257 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001258 if (!dev->target_name) {
1259 goto error;
1260 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001261
1262 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001263 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1264 if (rc || !dev_target) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001265 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001266 goto error;
1267 }
Michal Vaskob7b068c2016-02-16 13:51:50 +01001268 if (dev_target->module == lys_module(module)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001269 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001270 goto error;
1271 }
1272 /* mark the target module as deviated */
Michal Vaskoff006c12016-02-17 11:15:19 +01001273 dev_target->module->deviated = 1;
1274
1275 /* copy our imports to the deviated module (deviations may need them to work) */
1276 for (i = 0; i < module->imp_size; ++i) {
1277 for (j = 0; j < dev_target->module->imp_size; ++j) {
1278 if (module->imp[i].module == dev_target->module->imp[j].module) {
1279 break;
1280 }
1281 }
1282
1283 if (j < dev_target->module->imp_size) {
1284 /* import is already there */
1285 continue;
1286 }
1287
1288 /* copy the import, mark it as external */
1289 ++dev_target->module->imp_size;
1290 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1291 if (!dev_target->module->imp) {
1292 LOGMEM;
1293 goto error;
1294 }
1295 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1296 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1297 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1298 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1299 }
1300
1301 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1302 for (i = 0; i < dev_target->module->imp_size; ++i) {
1303 if (dev_target->module->imp[i].module == module) {
1304 break;
1305 }
1306 }
1307
1308 if (i == dev_target->module->imp_size) {
1309 ++dev_target->module->imp_size;
1310 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1311 if (!dev_target->module->imp) {
1312 LOGMEM;
1313 goto error;
1314 }
1315 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1316 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1317 if (module->rev_size) {
1318 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1319 } else {
1320 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1321 }
1322 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1323 } else {
1324 /* it could have been added by another deviating module that imported this deviating module */
1325 dev_target->module->imp[i].external = 2;
1326 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001327
1328 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001329 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1330 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001331 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001332 continue;
1333 }
1334
Radek Krejcieb00f512015-07-01 16:44:58 +02001335 if (!strcmp(child->name, "description")) {
1336 if (dev->dsc) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001337 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001338 goto error;
1339 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001340 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001341 if (!dev->dsc) {
1342 goto error;
1343 }
1344 } else if (!strcmp(child->name, "reference")) {
1345 if (dev->ref) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001346 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001347 goto error;
1348 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001349 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001350 if (!dev->ref) {
1351 goto error;
1352 }
1353 } else if (!strcmp(child->name, "deviate")) {
1354 c_dev++;
1355
Michal Vasko345da0a2015-12-02 10:35:55 +01001356 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001357 * further processed later
1358 */
1359 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001360
Radek Krejcieb00f512015-07-01 16:44:58 +02001361 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001362 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001363 goto error;
1364 }
1365
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001366 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001367 }
1368
1369 if (c_dev) {
1370 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001371 if (!dev->deviate) {
1372 LOGMEM;
1373 goto error;
1374 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001375 }
1376
1377 LY_TREE_FOR(yin->child, develem) {
1378 /* init */
1379 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001380 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001381 c_must = 0;
1382 c_uniq = 0;
1383
1384 /* get deviation type */
1385 GETVAL(value, develem, "value");
1386 if (!strcmp(value, "not-supported")) {
1387 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1388 /* no property expected in this case */
1389 if (develem->child) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001390 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001391 goto error;
1392 }
1393
Radek Krejci5b917642015-07-02 09:03:13 +02001394 /* and neither any other deviate statement is expected,
1395 * not-supported deviation must be the only deviation of the target
1396 */
1397 if (dev->deviate_size || develem->next) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001398 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001399 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001400 goto error;
1401 }
1402
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001403 /* you cannot remove a key leaf */
1404 if ((dev_target->nodetype == LYS_LEAF) && dev_target->parent && (dev_target->parent->nodetype == LYS_LIST)) {
1405 for (i = 0; i < ((struct lys_node_list *)dev_target->parent)->keys_size; ++i) {
1406 if (((struct lys_node_list *)dev_target->parent)->keys[i] == (struct lys_node_leaf *)dev_target) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001407 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_NONE, NULL, value, develem->name);
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001408 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot remove a list key.");
1409 goto error;
1410 }
1411 }
1412 }
Radek Krejci5b917642015-07-02 09:03:13 +02001413
Michal Vaskoff006c12016-02-17 11:15:19 +01001414 /* unlink and store the original node */
1415 lys_node_unlink(dev_target);
1416 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001417
Radek Krejci5b917642015-07-02 09:03:13 +02001418 dev->deviate_size = 1;
1419 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001420 } else if (!strcmp(value, "add")) {
1421 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1422 } else if (!strcmp(value, "replace")) {
1423 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1424 } else if (!strcmp(value, "delete")) {
1425 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1426 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001427 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001428 goto error;
1429 }
1430 d = &dev->deviate[dev->deviate_size];
1431
Michal Vaskoff006c12016-02-17 11:15:19 +01001432 /* store a shallow copy of the original node */
1433 if (!dev->orig_node) {
1434 memset(&tmp_unres, 0, sizeof tmp_unres);
1435 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1436 /* just to be safe */
1437 if (tmp_unres.count) {
1438 LOGINT;
1439 goto error;
1440 }
1441 }
1442
Radek Krejcieb00f512015-07-01 16:44:58 +02001443 /* process deviation properties */
1444 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001445 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1446 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001447 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001448 continue;
1449 }
1450
Radek Krejcieb00f512015-07-01 16:44:58 +02001451 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001452 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001453 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 goto error;
1455 }
1456
1457 /* for we deviate from RFC 6020 and allow config property even it is/is not
1458 * specified in the target explicitly since config property inherits. So we expect
1459 * that config is specified in every node. But for delete, we check that the value
1460 * is the same as here in deviation
1461 */
1462 GETVAL(value, child, "value");
1463 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001464 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001465 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001466 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001467 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001468 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001469 goto error;
1470 }
1471
1472 if (d->mod == LY_DEVIATE_DEL) {
1473 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001474 if ((d->flags & LYS_CONFIG_MASK) != (dev_target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001475 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001476 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001477 goto error;
1478 }
1479 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001480 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001481
1482 /* ... and inherit config value from the target's parent */
Michal Vasko60f4b452016-02-12 11:02:55 +01001483 if (dev_target->parent) {
1484 dev_target->flags |= dev_target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001485 } else {
1486 /* default config is true */
Michal Vasko60f4b452016-02-12 11:02:55 +01001487 dev_target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001488 }
1489 } else { /* add and replace are the same in this case */
1490 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001491 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001492
1493 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001494 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001495 }
1496 } else if (!strcmp(child->name, "default")) {
1497 if (d->dflt) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001498 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001499 goto error;
1500 }
1501 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001502 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001503
Michal Vasko60f4b452016-02-12 11:02:55 +01001504 if (dev_target->nodetype == LYS_CHOICE) {
1505 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001506
1507 if (d->mod == LY_DEVIATE_ADD) {
1508 /* check that there is no current value */
1509 if (choice->dflt) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001510 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001511 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 goto error;
1513 }
1514 }
1515
Michal Vasko3edeaf72016-02-11 13:17:43 +01001516 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001517 if (rc || !node) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001518 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001519 goto error;
1520 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001521 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001522 if (!choice->dflt || (choice->dflt != node)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001523 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001524 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001525 goto error;
1526 }
1527 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001528 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001529 if (!choice->dflt) {
1530 /* default branch not found */
Michal Vaskoe5e06292016-02-26 09:56:41 +01001531 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 goto error;
1533 }
1534 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001535 } else if (dev_target->nodetype == LYS_LEAF) {
1536 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001537
1538 if (d->mod == LY_DEVIATE_ADD) {
1539 /* check that there is no current value */
1540 if (leaf->dflt) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001541 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001542 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 goto error;
1544 }
1545 }
1546
1547 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001548 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001549 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001550 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001551 goto error;
1552 }
1553 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001554 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 leaf->dflt = NULL;
1556 } else { /* add (already checked) and replace */
1557 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001558 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001559
1560 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001561 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 }
1563 } else {
1564 /* invalid target for default value */
Michal Vaskoe5e06292016-02-26 09:56:41 +01001565 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001566 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001567 goto error;
1568 }
1569 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001570 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001571 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001572 goto error;
1573 }
1574
1575 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001576 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001577 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001578 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001579 goto error;
1580 }
1581
1582 GETVAL(value, child, "value");
1583 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001584 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001585 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001586 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001588 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001589 goto error;
1590 }
1591
1592 if (d->mod == LY_DEVIATE_ADD) {
1593 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001594 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001595 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001596 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001597 goto error;
1598 }
1599 }
1600
1601 if (d->mod == LY_DEVIATE_DEL) {
1602 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001603 if ((d->flags & LYS_MAND_MASK) != (dev_target->flags & LYS_MAND_MASK)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001604 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001605 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 goto error;
1607 }
1608 /* remove current mandatory value of the target */
Michal Vasko60f4b452016-02-12 11:02:55 +01001609 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001610 } else { /* add (already checked) and replace */
1611 /* remove current mandatory value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001612 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001613
1614 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001615 dev_target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001616 }
1617 } else if (!strcmp(child->name, "min-elements")) {
1618 if (f_min) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001619 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001620 goto error;
1621 }
1622 f_min = 1;
1623
Michal Vasko60f4b452016-02-12 11:02:55 +01001624 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001625 goto error;
1626 }
1627 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001628 if (f_max) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001629 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001630 goto error;
1631 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001632 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001633
Michal Vasko60f4b452016-02-12 11:02:55 +01001634 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 goto error;
1636 }
1637 } else if (!strcmp(child->name, "must")) {
1638 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001639 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001640 continue;
1641 } else if (!strcmp(child->name, "type")) {
1642 if (d->type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001643 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 goto error;
1645 }
1646
1647 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001648 if (dev_target->nodetype == LYS_LEAF) {
1649 t = &((struct lys_node_leaf *)dev_target)->type;
1650 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1651 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001652 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001653 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001654 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001655 goto error;
1656 }
1657
1658 if (d->mod == LY_DEVIATE_ADD) {
1659 /* not allowed, type is always present at the target */
Michal Vaskoe5e06292016-02-26 09:56:41 +01001660 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001661 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001662 goto error;
1663 } else if (d->mod == LY_DEVIATE_DEL) {
1664 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe5e06292016-02-26 09:56:41 +01001665 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001666 LOGVAL(LYE_SPEC, 0, 0, NULL, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 goto error;
1668 }
1669
1670 /* replace */
1671 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001672 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001673
1674 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001675 /* HACK for unres */
1676 t->der = (struct lys_tpdf *)child;
Michal Vasko60f4b452016-02-12 11:02:55 +01001677 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001678 goto error;
1679 }
1680 d->type = t;
1681 } else if (!strcmp(child->name, "unique")) {
1682 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001683 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001684 continue;
1685 } else if (!strcmp(child->name, "units")) {
1686 if (d->units) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001687 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001688 goto error;
1689 }
1690
1691 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001692 if (dev_target->nodetype == LYS_LEAFLIST) {
1693 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1694 } else if (dev_target->nodetype == LYS_LEAF) {
1695 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001696 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001697 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001698 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001699 goto error;
1700 }
1701
1702 /* get units value */
1703 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001704 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001705
1706 /* apply to target */
1707 if (d->mod == LY_DEVIATE_ADD) {
1708 /* check that there is no current value */
1709 if (*stritem) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001710 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001711 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001712 goto error;
1713 }
1714 }
1715
1716 if (d->mod == LY_DEVIATE_DEL) {
1717 /* check values */
1718 if (*stritem != d->units) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001719 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001720 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001721 goto error;
1722 }
1723 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001724 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 } else { /* add (already checked) and replace */
1726 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001727 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001728
1729 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001730 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001731 }
1732 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001733 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001734 goto error;
1735 }
1736
Michal Vasko88c29542015-11-27 14:57:53 +01001737 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 }
1739
1740 if (c_must) {
1741 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001742 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001743 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001744 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1745 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 break;
Radek Krejci76512572015-08-04 09:47:08 +02001747 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001748 trg_must = &((struct lys_node_container *)dev_target)->must;
1749 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001750 break;
Radek Krejci76512572015-08-04 09:47:08 +02001751 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001752 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1753 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001754 break;
Radek Krejci76512572015-08-04 09:47:08 +02001755 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001756 trg_must = &((struct lys_node_list *)dev_target)->must;
1757 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001758 break;
Radek Krejci76512572015-08-04 09:47:08 +02001759 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001760 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1761 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001762 break;
1763 default:
Michal Vaskoe5e06292016-02-26 09:56:41 +01001764 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001765 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001766 goto error;
1767 }
1768
1769 if (d->mod == LY_DEVIATE_RPL) {
1770 /* remove target's musts and allocate new array for it */
1771 if (!*trg_must) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001772 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_NONE, NULL, "replace", "deviate");
Radek Krejciadb57612016-02-16 13:34:34 +01001773 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001774 goto error;
1775 }
1776
1777 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001778 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 }
1780 free(*trg_must);
1781 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1782 d->must_size = c_must;
1783 *trg_must_size = 0;
1784 } else if (d->mod == LY_DEVIATE_ADD) {
1785 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001786 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001787 if (!d->must) {
1788 LOGMEM;
1789 goto error;
1790 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001792 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001793 d->must_size = c_must;
1794 } else { /* LY_DEVIATE_DEL */
1795 d->must = calloc(c_must, sizeof *d->must);
1796 }
Michal Vasko253035f2015-12-17 16:58:13 +01001797 if (!d->must) {
1798 LOGMEM;
1799 goto error;
1800 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 }
1802 if (c_uniq) {
1803 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001804 if (dev_target->nodetype != LYS_LIST) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001805 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001806 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 goto error;
1808 }
1809
Michal Vasko60f4b452016-02-12 11:02:55 +01001810 list = (struct lys_node_list *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 if (d->mod == LY_DEVIATE_RPL) {
1812 /* remove target's unique and allocate new array for it */
1813 if (!list->unique) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01001814 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_NONE, NULL, "replace", "deviate");
Radek Krejciadb57612016-02-16 13:34:34 +01001815 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 goto error;
1817 }
1818
1819 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001820 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001821 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001822 }
1823 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 }
1825 free(list->unique);
1826 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1827 d->unique_size = c_uniq;
1828 list->unique_size = 0;
1829 } else if (d->mod == LY_DEVIATE_ADD) {
1830 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001831 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001832 list->unique = d->unique;
1833 d->unique = &list->unique[list->unique_size];
1834 d->unique_size = c_uniq;
1835 } else { /* LY_DEVIATE_DEL */
1836 d->unique = calloc(c_uniq, sizeof *d->unique);
1837 }
Michal Vasko253035f2015-12-17 16:58:13 +01001838 if (!d->unique) {
1839 LOGMEM;
1840 goto error;
1841 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001842 }
1843
1844 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001845 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001846 if (!strcmp(child->name, "must")) {
1847 if (d->mod == LY_DEVIATE_DEL) {
1848 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1849 goto error;
1850 }
1851
1852 /* find must to delete, we are ok with just matching conditions */
1853 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001854 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001856 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 /* ... and maintain the array */
1858 (*trg_must_size)--;
1859 if (i != *trg_must_size) {
1860 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1861 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1862 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1863 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1864 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1865 }
1866 if (!(*trg_must_size)) {
1867 free(*trg_must);
1868 *trg_must = NULL;
1869 } else {
1870 (*trg_must)[*trg_must_size].expr = NULL;
1871 (*trg_must)[*trg_must_size].dsc = NULL;
1872 (*trg_must)[*trg_must_size].ref = NULL;
1873 (*trg_must)[*trg_must_size].eapptag = NULL;
1874 (*trg_must)[*trg_must_size].emsg = NULL;
1875 }
1876
1877 i = -1; /* set match flag */
1878 break;
1879 }
1880 }
1881 d->must_size++;
1882 if (i != -1) {
1883 /* no match found */
Michal Vaskoe5e06292016-02-26 09:56:41 +01001884 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001885 d->must[d->must_size - 1].expr, child->name);
1886 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001887 goto error;
1888 }
1889 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001890 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1891 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001892 goto error;
1893 }
1894 (*trg_must_size)++;
1895 }
1896 } else if (!strcmp(child->name, "unique")) {
1897 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001898 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001899 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001900 goto error;
1901 }
1902
1903 /* find unique structures to delete */
1904 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001905 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001906 continue;
1907 }
1908
Radek Krejci581ce772015-11-10 17:22:40 +01001909 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001910 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001911 break;
1912 }
1913 }
1914
Radek Krejci581ce772015-11-10 17:22:40 +01001915 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001916 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001917 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001918 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001919 }
1920 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001921 /* ... and maintain the array */
1922 list->unique_size--;
1923 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001924 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1925 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001926 }
1927
1928 if (!list->unique_size) {
1929 free(list->unique);
1930 list->unique = NULL;
1931 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001932 list->unique[list->unique_size].expr_size = 0;
1933 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001934 }
1935
1936 i = -1; /* set match flag */
1937 break;
1938 }
1939 }
1940
1941 d->unique_size++;
1942 if (i != -1) {
1943 /* no match found */
Michal Vaskoe5e06292016-02-26 09:56:41 +01001944 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01001945 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001946 goto error;
1947 }
1948 } else { /* replace or add */
Michal Vasko60f4b452016-02-12 11:02:55 +01001949 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001950 list->unique_size++;
1951 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001952 goto error;
1953 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001954 }
1955 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001956 }
Radek Krejci5b917642015-07-02 09:03:13 +02001957
1958 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001959 }
1960
Radek Krejcieb00f512015-07-01 16:44:58 +02001961 return EXIT_SUCCESS;
1962
1963error:
1964
Radek Krejcieb00f512015-07-01 16:44:58 +02001965 return EXIT_FAILURE;
1966}
1967
Michal Vasko0d343d12015-08-24 14:57:36 +02001968/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001969static int
Radek Krejcib8048692015-08-05 13:36:34 +02001970fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Michal Vaskof02e3742015-08-05 16:27:02 +02001971 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001972{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001974 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001975 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001976 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001977
Michal Vasko591e0b22015-08-13 13:53:43 +02001978 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001980 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001981 if (!aug->target_name) {
1982 goto error;
1983 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001985
Michal Vasko1d87a922015-08-21 12:57:16 +02001986 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001987 goto error;
1988 }
1989
1990 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001991 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1992 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001993 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001994 continue;
1995 }
1996
Radek Krejci3cf9e222015-06-18 11:37:50 +02001997 if (!strcmp(child->name, "if-feature")) {
1998 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002000 } else if (!strcmp(child->name, "when")) {
2001 if (aug->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002002 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002003 goto error;
2004 }
2005
2006 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002007 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002008 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002009 goto error;
2010 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002011 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002013
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002014 /* check allowed data sub-statements */
2015 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002016 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002018 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002019 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002021 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002026 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002027 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002028 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002029 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002030 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002031 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002032 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002033 goto error;
2034 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002035
Radek Krejci1d82ef62015-08-07 14:44:40 +02002036 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002037 goto error;
2038 }
2039
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002041 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002042 }
2043
2044 if (c) {
2045 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002046 if (!aug->features) {
2047 LOGMEM;
2048 goto error;
2049 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002050 }
2051
2052 LY_TREE_FOR_SAFE(yin->child, next, child) {
2053 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002054 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002055 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002056 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002057 goto error;
2058 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002059 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002060 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002061 }
2062
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002063 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002064 * connected to the tree and adjusted (if possible right now).
2065 * However, if this is augment in a uses, it gets resolved
2066 * when the uses does and cannot be resolved now for sure
2067 * (the grouping was not yet copied into uses).
2068 */
2069 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko7178e692016-02-12 15:58:05 +01002070 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin)) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002071 goto error;
2072 }
Michal Vasko49291b32015-08-06 09:49:41 +02002073 }
Radek Krejci106efc02015-06-10 14:36:27 +02002074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002076
2077error:
2078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002080}
2081
Michal Vasko0d343d12015-08-24 14:57:36 +02002082/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083static int
Michal Vasko0d204592015-10-07 09:50:04 +02002084fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002085{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 struct lyxml_elem *sub, *next;
2087 const char *value;
2088 char *endptr;
2089 int f_mand = 0, f_min = 0, f_max = 0;
2090 int c_must = 0;
2091 int r;
2092 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002093
Radek Krejci76512572015-08-04 09:47:08 +02002094 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 goto error;
2096 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002097
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002098 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002099 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002100 if (!rfn->target_name) {
2101 goto error;
2102 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002105 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2106 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002107 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002108 continue;
2109 }
2110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 /* limited applicability */
2112 if (!strcmp(sub->name, "default")) {
2113 /* leaf or choice */
2114 if (rfn->mod.dflt) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002115 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 goto error;
2117 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 /* check possibility of statements combination */
2120 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002121 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 if (!rfn->target_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002123 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 goto error;
2125 }
2126 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002127 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 GETVAL(value, sub, "value");
2131 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2132 } else if (!strcmp(sub->name, "mandatory")) {
2133 /* leaf, choice or anyxml */
2134 if (f_mand) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002135 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 goto error;
2137 }
2138 /* just checking the flags in leaf is not sufficient, we would allow
2139 * multiple mandatory statements with the "false" value
2140 */
2141 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 /* check possibility of statements combination */
2144 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002145 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 if (!rfn->target_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002147 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 goto error;
2149 }
2150 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002151 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 GETVAL(value, sub, "value");
2155 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002156 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002158 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002160 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 goto error;
2162 }
2163 } else if (!strcmp(sub->name, "min-elements")) {
2164 /* list or leaf-list */
2165 if (f_min) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002166 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 goto error;
2168 }
2169 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 /* check possibility of statements combination */
2172 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002173 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 if (!rfn->target_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002175 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 goto error;
2177 }
2178 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002179 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 GETVAL(value, sub, "value");
2183 while (isspace(value[0])) {
2184 value++;
2185 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 /* convert it to uint32_t */
2188 errno = 0;
2189 endptr = NULL;
2190 val = strtoul(value, &endptr, 10);
2191 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002192 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 goto error;
2194 }
2195 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 /* magic - bit 3 in flags means min set */
2198 rfn->flags |= 0x04;
2199 } else if (!strcmp(sub->name, "max-elements")) {
2200 /* list or leaf-list */
2201 if (f_max) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002202 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 goto error;
2204 }
2205 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 /* check possibility of statements combination */
2208 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002209 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 if (!rfn->target_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002211 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 goto error;
2213 }
2214 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002215 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 GETVAL(value, sub, "value");
2219 while (isspace(value[0])) {
2220 value++;
2221 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002222
Radek Krejci0d7b2472016-02-12 11:11:03 +01002223 if (!strcmp(value, "unbounded")) {
2224 rfn->mod.list.max = 0;
2225 } else {
2226 /* convert it to uint32_t */
2227 errno = 0;
2228 endptr = NULL;
2229 val = strtoul(value, &endptr, 10);
2230 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002231 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002232 goto error;
2233 }
2234 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 /* magic - bit 4 in flags means min set */
2238 rfn->flags |= 0x08;
2239 } else if (!strcmp(sub->name, "presence")) {
2240 /* container */
2241 if (rfn->mod.presence) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002242 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 goto error;
2244 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 /* check possibility of statements combination */
2247 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002248 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 if (!rfn->target_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002250 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 goto error;
2252 }
2253 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002254 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 GETVAL(value, sub, "value");
2258 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2259 } else if (!strcmp(sub->name, "must")) {
2260 /* leaf-list, list, container or anyxml */
2261 /* check possibility of statements combination */
2262 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002263 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 if (!rfn->target_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002265 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 goto error;
2267 }
2268 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002269 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002273 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002274
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002276 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 goto error;
2278 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002279
Michal Vasko345da0a2015-12-02 10:35:55 +01002280 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 /* process nodes with cardinality of 0..n */
2284 if (c_must) {
2285 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002286 if (!rfn->must) {
2287 LOGMEM;
2288 goto error;
2289 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 }
Radek Krejci73adb602015-07-02 18:07:40 +02002291 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002292 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2293 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002294 if (r) {
2295 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002300
2301error:
2302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002304}
2305
Michal Vasko0d343d12015-08-24 14:57:36 +02002306/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307static int
Radek Krejcib8048692015-08-05 13:36:34 +02002308fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002309{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 struct lyxml_elem *child;
2311 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002312 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002315 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2316 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002317 continue;
2318 }
2319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 if (!strcmp(child->name, "prefix")) {
2321 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002322 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 goto error;
2324 }
2325 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2326 } else if (!strcmp(child->name, "revision-date")) {
2327 if (imp->rev[0]) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002328 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 goto error;
2330 }
2331 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002332 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002333 goto error;
2334 }
2335 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2336 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002337 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 goto error;
2339 }
2340 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 /* check mandatory information */
2343 if (!imp->prefix) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002344 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002345 goto error;
2346 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002349
2350 /* check for circular import, store it if passed */
2351 if (!module->ctx->models.parsing) {
2352 count = 0;
2353 } else {
2354 for (count = 0; module->ctx->models.parsing[count]; ++count) {
Radek Krejci749190d2016-02-18 16:26:25 +01002355 if (ly_strequal(value, module->ctx->models.parsing[count], 1)) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002356 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2357 goto error;
2358 }
2359 }
2360 }
2361 ++count;
2362 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002363 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2364 if (!module->ctx->models.parsing) {
2365 LOGMEM;
2366 goto error;
2367 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002368 module->ctx->models.parsing[count - 1] = value;
2369 module->ctx->models.parsing[count] = NULL;
2370
2371 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002372 imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002374 /* whether to use a user callback is decided in the function */
2375 imp->module = (struct lys_module *)ly_ctx_load_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002376 }
2377
2378 /* remove the new module name now that its parsing is finished (even if failed) */
Radek Krejci749190d2016-02-18 16:26:25 +01002379 if (module->ctx->models.parsing[count] || !ly_strequal(module->ctx->models.parsing[count - 1], value, 1)) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002380 LOGINT;
2381 }
2382 --count;
2383 if (count) {
2384 module->ctx->models.parsing[count] = NULL;
2385 } else {
2386 free(module->ctx->models.parsing);
2387 module->ctx->models.parsing = NULL;
2388 }
2389
2390 /* check the result */
2391 if (!imp->module) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002392 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002393 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2394 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002398
2399error:
2400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002402}
2403
Michal Vasko0d343d12015-08-24 14:57:36 +02002404/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002406fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2407 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002408{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002409 struct lyxml_elem *child;
2410 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002411 char *module_data;
Michal Vaskod3e975b2016-03-03 15:40:21 +01002412 void (*module_data_free)(void *module_data) = NULL;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002413 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko5a721fd2016-02-16 12:16:48 +01002414 int count, i;
Radek Krejciefaeba32015-05-27 14:30:57 +02002415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002417 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2418 /* garbage */
2419 continue;
2420 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 if (!strcmp(child->name, "revision-date")) {
2422 if (inc->rev[0]) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002423 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 goto error;
2425 }
2426 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002427 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002428 goto error;
2429 }
2430 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2431 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002432 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 goto error;
2434 }
2435 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002438
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002439 /* check that the submodule was not included yet (previous submodule could have included it) */
2440 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci749190d2016-02-18 16:26:25 +01002441 if (module->inc[i].submodule && (ly_strequal(module->inc[i].submodule->name, value, 1))) {
Michal Vasko5ff78822016-02-12 09:33:31 +01002442 /* copy the duplicate into the result */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002443 memcpy(inc, &module->inc[i], sizeof *inc);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002444
Michal Vasko5ff78822016-02-12 09:33:31 +01002445 if (submodule) {
2446 /* we don't care if it was external or not */
2447 inc->external = 0;
2448 } else if (inc->external) {
2449 /* remove the duplicate */
2450 --module->inc_size;
2451 memmove(&module->inc[i], &module->inc[i + 1], (module->inc_size - i) * sizeof *inc);
2452 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
2453
2454 /* it is no longer external */
2455 inc->external = 0;
2456 }
2457 /* if !submodule && !inc->external, we just create a duplicate so it is detected and ended with error */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002458
2459 return EXIT_SUCCESS;
2460 }
2461 }
2462
Michal Vasko1b882eb2015-10-22 11:43:14 +02002463 /* check for circular include, store it if passed */
2464 if (!module->ctx->models.parsing) {
2465 count = 0;
2466 } else {
2467 for (count = 0; module->ctx->models.parsing[count]; ++count) {
Radek Krejci749190d2016-02-18 16:26:25 +01002468 if (ly_strequal(value, module->ctx->models.parsing[count], 1)) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002469 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2470 goto error;
2471 }
2472 }
2473 }
2474 ++count;
2475 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002476 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2477 if (!module->ctx->models.parsing) {
2478 LOGMEM;
2479 goto error;
2480 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002481 module->ctx->models.parsing[count - 1] = value;
2482 module->ctx->models.parsing[count] = NULL;
2483
2484 /* try to load the submodule */
Radek Krejciff4874d2016-03-07 12:30:50 +01002485 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule2(module, value);
Radek Krejcie7973552016-03-07 08:12:01 +01002486 if (inc->submodule) {
2487 if (inc->rev[0]) {
2488 if (!inc->submodule->rev_size || !ly_strequal(inc->rev, inc->submodule->rev[0].date, 1)) {
2489 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL,
Radek Krejciff4874d2016-03-07 12:30:50 +01002490 "Multiple revisions of the same submodule included.");
Radek Krejcie7973552016-03-07 08:12:01 +01002491 goto error;
2492 }
2493 }
Radek Krejciff4874d2016-03-07 12:30:50 +01002494 } else {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002495 if (module->ctx->module_clb) {
2496 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2497 &format, &module_data_free);
2498 if (module_data) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01002499 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002500 if (module_data_free) {
2501 module_data_free(module_data);
2502 } else {
2503 free(module_data);
2504 }
2505 } else {
2506 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2507 }
2508 } else {
Michal Vasko5a721fd2016-02-16 12:16:48 +01002509 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
2510 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002511 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002512 }
2513
2514 /* remove the new submodule name now that its parsing is finished (even if failed) */
Radek Krejci749190d2016-02-18 16:26:25 +01002515 if (module->ctx->models.parsing[count] || !ly_strequal(module->ctx->models.parsing[count - 1], value, 1)) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002516 LOGINT;
2517 }
2518 --count;
2519 if (count) {
2520 module->ctx->models.parsing[count] = NULL;
2521 } else {
2522 free(module->ctx->models.parsing);
2523 module->ctx->models.parsing = NULL;
2524 }
2525
2526 /* check the result */
Michal Vasko5a721fd2016-02-16 12:16:48 +01002527 if (!inc->submodule) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002528 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002529 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2530 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002534
2535error:
2536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002538}
2539
Michal Vasko0d343d12015-08-24 14:57:36 +02002540/* logs directly
2541 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002542 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002543 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002544 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002545 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546static int
Radek Krejcib8048692015-08-05 13:36:34 +02002547read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002548 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002549{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 const char *value;
2551 struct lyxml_elem *sub, *next;
2552 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002554 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002555 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002558 if (opt & OPT_IDENT) {
2559 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002560 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002561 goto error;
2562 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002563 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002565
Radek Krejci6764bb32015-07-03 15:16:04 +02002566 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002567 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002568 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002569 }
2570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 /* process local parameters */
2572 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002573 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002574 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002575 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002576 continue;
2577 }
2578 if (strcmp(sub->ns->value, LY_NSYIN)) {
2579 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002580 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002581 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002582 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002583 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002584 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002585 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002586 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002587 goto error;
2588 }
2589 }
2590
2591 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002592 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002593 continue;
2594 }
2595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002596 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002597 if (node->dsc) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002598 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002599 goto error;
2600 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002601 node->dsc = read_yin_subnode(ctx, sub, "text");
2602 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002603 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 }
2605 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002606 if (node->ref) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002607 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002608 goto error;
2609 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002610 node->ref = read_yin_subnode(ctx, sub, "text");
2611 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002612 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002613 }
2614 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002615 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002616 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 goto error;
2618 }
2619 GETVAL(value, sub, "value");
2620 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002621 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002622 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002624 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002625 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002626 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002627 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002628 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002629 }
2630 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002631 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002632 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 goto error;
2634 }
2635 GETVAL(value, sub, "value");
2636 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002637 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002639 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002641 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002642 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 }
2644 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002645 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 continue;
2647 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002648 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002650
Radek Krejci1d82ef62015-08-07 14:44:40 +02002651 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002652 /* get config flag from parent */
2653 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002654 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002655 } else {
2656 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002657 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 }
2659 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002661 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002662
2663error:
2664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002666}
2667
Michal Vasko0d343d12015-08-24 14:57:36 +02002668/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002669static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002670read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002671{
Radek Krejci76512572015-08-04 09:47:08 +02002672 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002673 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002674 const char *value;
2675
2676 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002677 if (!retval) {
2678 LOGMEM;
2679 return NULL;
2680 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002681
2682 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002683 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002684 if (!retval->cond) {
2685 goto error;
2686 }
Michal Vasko77dc5652016-02-15 12:32:42 +01002687 if (lyxp_syntax_check(retval->cond, LOGLINE(yin))) {
2688 goto error;
2689 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002690
Radek Krejci73adb602015-07-02 18:07:40 +02002691 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002692 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2693 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002694 continue;
2695 }
2696
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002697 if (!strcmp(child->name, "description")) {
2698 if (retval->dsc) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002699 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002700 goto error;
2701 }
2702 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2703 if (!retval->dsc) {
2704 goto error;
2705 }
2706 } else if (!strcmp(child->name, "reference")) {
2707 if (retval->ref) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002708 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002709 goto error;
2710 }
2711 retval->ref = read_yin_subnode(module->ctx, child, "text");
2712 if (!retval->ref) {
2713 goto error;
2714 }
2715 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002716 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002717 goto error;
2718 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002719 }
2720
2721 return retval;
2722
2723error:
2724
Michal Vasko0308dd62015-10-07 09:14:40 +02002725 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002726 return NULL;
2727}
2728
Michal Vasko0d343d12015-08-24 14:57:36 +02002729/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002730static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002731read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2732 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002733{
Michal Vasko29fc0182015-08-24 15:02:39 +02002734 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002735 struct lys_node_case *cs;
2736 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002737 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002738
Radek Krejcie867c852015-08-27 09:52:34 +02002739 /* init */
2740 memset(&root, 0, sizeof root);
2741
Radek Krejci1d82ef62015-08-07 14:44:40 +02002742 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002743 if (!cs) {
2744 LOGMEM;
2745 return NULL;
2746 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002747 cs->nodetype = LYS_CASE;
2748 cs->prev = (struct lys_node *)cs;
2749 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002750
Radek Krejci6a113852015-07-03 16:04:20 +02002751 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002752 goto error;
2753 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002754
Radek Krejcia9544502015-08-14 08:24:29 +02002755 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2756
Michal Vasko3a0043f2015-08-12 12:11:30 +02002757 /* insert the node into the schema tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +01002758 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002759 goto error;
2760 }
2761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002762 /* process choice's specific children */
2763 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002764 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2765 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002766 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002767 continue;
2768 }
2769
Michal Vasko29fc0182015-08-24 15:02:39 +02002770 if (!strcmp(sub->name, "container") ||
2771 !strcmp(sub->name, "leaf-list") ||
2772 !strcmp(sub->name, "leaf") ||
2773 !strcmp(sub->name, "list") ||
2774 !strcmp(sub->name, "uses") ||
2775 !strcmp(sub->name, "choice") ||
2776 !strcmp(sub->name, "anyxml")) {
2777
Michal Vaskof3930de2015-10-22 12:03:59 +02002778 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002779 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002780 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002781 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002782 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002783 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002784 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002785 if (cs->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002786 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002787 goto error;
2788 }
2789
Radek Krejci1d82ef62015-08-07 14:44:40 +02002790 cs->when = read_yin_when(module, sub);
2791 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002792 goto error;
2793 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002794
Michal Vasko345da0a2015-12-02 10:35:55 +01002795 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002796 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002797 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002798 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002801
Radek Krejci3cf9e222015-06-18 11:37:50 +02002802 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002803 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002804 if (!cs->features) {
2805 LOGMEM;
2806 goto error;
2807 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002808 }
Radek Krejci73adb602015-07-02 18:07:40 +02002809 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002810 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002811 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002812 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002813 goto error;
2814 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002815 }
Radek Krejcib388c152015-06-04 17:03:03 +02002816
Michal Vasko29fc0182015-08-24 15:02:39 +02002817 /* last part - process data nodes */
2818 LY_TREE_FOR_SAFE(root.child, next, sub) {
2819 if (!strcmp(sub->name, "container")) {
2820 node = read_yin_container(module, retval, sub, resolve, unres);
2821 } else if (!strcmp(sub->name, "leaf-list")) {
2822 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2823 } else if (!strcmp(sub->name, "leaf")) {
2824 node = read_yin_leaf(module, retval, sub, resolve, unres);
2825 } else if (!strcmp(sub->name, "list")) {
2826 node = read_yin_list(module, retval, sub, resolve, unres);
2827 } else if (!strcmp(sub->name, "choice")) {
2828 node = read_yin_choice(module, retval, sub, resolve, unres);
2829 } else if (!strcmp(sub->name, "uses")) {
2830 node = read_yin_uses(module, retval, sub, resolve, unres);
2831 } else if (!strcmp(sub->name, "anyxml")) {
2832 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2833 }
2834 if (!node) {
2835 goto error;
2836 }
2837
Michal Vasko345da0a2015-12-02 10:35:55 +01002838 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002839 }
2840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002842
2843error:
2844
Michal Vasko29fc0182015-08-24 15:02:39 +02002845 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002846 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002847 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002848 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002851}
2852
Michal Vasko0d343d12015-08-24 14:57:36 +02002853/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002854static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002855read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002856{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 struct lyxml_elem *sub, *next;
2858 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002859 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002860 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002861 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002862 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002864 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002865 if (!choice) {
2866 LOGMEM;
2867 return NULL;
2868 }
Radek Krejci76512572015-08-04 09:47:08 +02002869 choice->nodetype = LYS_CHOICE;
2870 choice->prev = (struct lys_node *)choice;
2871 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002872
Michal Vaskoe0c59842015-09-24 13:52:20 +02002873 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2874 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 goto error;
2876 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002877
Radek Krejcia9544502015-08-14 08:24:29 +02002878 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2879
Michal Vasko3a0043f2015-08-12 12:11:30 +02002880 /* insert the node into the schema tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +01002881 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002882 goto error;
2883 }
2884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 /* process choice's specific children */
2886 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002887 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2888 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002889 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002890 continue;
2891 }
2892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002894 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 goto error;
2896 }
2897 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002898 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 goto error;
2900 }
2901 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002902 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002903 goto error;
2904 }
2905 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002906 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907 goto error;
2908 }
2909 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002910 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 goto error;
2912 }
2913 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002914 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 goto error;
2916 }
2917 } else if (!strcmp(sub->name, "default")) {
2918 if (dflt_str) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002919 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 goto error;
2921 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002922 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 } else if (!strcmp(sub->name, "mandatory")) {
2924 if (f_mand) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002925 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 goto error;
2927 }
2928 /* just checking the flags in leaf is not sufficient, we would allow
2929 * multiple mandatory statements with the "false" value
2930 */
2931 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 GETVAL(value, sub, "value");
2934 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002935 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002936 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002937 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002938 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002939 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002940 goto error;
2941 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002942 } else if (!strcmp(sub->name, "when")) {
2943 if (choice->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002944 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002945 goto error;
2946 }
2947
2948 choice->when = read_yin_when(module, sub);
2949 if (!choice->when) {
2950 goto error;
2951 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002952 } else if (!strcmp(sub->name, "if-feature")) {
2953 c_ftrs++;
2954
Michal Vasko345da0a2015-12-02 10:35:55 +01002955 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002956 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002958 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002960 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002961
Radek Krejci1d82ef62015-08-07 14:44:40 +02002962 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002963 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002965
Radek Krejci3cf9e222015-06-18 11:37:50 +02002966 if (c_ftrs) {
2967 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002968 if (!choice->features) {
2969 LOGMEM;
2970 goto error;
2971 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002972 }
2973
Radek Krejci73adb602015-07-02 18:07:40 +02002974 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002975 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002976 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002977 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002978 goto error;
2979 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002980 }
2981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002982 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002983 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01002984 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2986 goto error;
2987 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002989 /* link default with the case */
2990 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002991 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002992 goto error;
2993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002997
2998error:
2999
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003000 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003003}
3004
Michal Vasko0d343d12015-08-24 14:57:36 +02003005/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003006static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003007read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003008 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003009{
Radek Krejci76512572015-08-04 09:47:08 +02003010 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003011 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003012 struct lyxml_elem *sub, *next;
3013 const char *value;
3014 int r;
3015 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003016 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003019 if (!anyxml) {
3020 LOGMEM;
3021 return NULL;
3022 }
Radek Krejci76512572015-08-04 09:47:08 +02003023 anyxml->nodetype = LYS_ANYXML;
3024 anyxml->prev = (struct lys_node *)anyxml;
3025 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003026
Michal Vaskoe0c59842015-09-24 13:52:20 +02003027 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3028 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 goto error;
3030 }
Radek Krejci863c2852015-06-03 15:47:11 +02003031
Radek Krejcia9544502015-08-14 08:24:29 +02003032 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003033
Michal Vasko4f0dad02016-02-15 14:08:23 +01003034 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003035 goto error;
3036 }
3037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003039 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3040 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003041 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003042 continue;
3043 }
3044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 if (!strcmp(sub->name, "mandatory")) {
3046 if (f_mand) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003047 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 goto error;
3049 }
3050 /* just checking the flags in leaf is not sufficient, we would allow
3051 * multiple mandatory statements with the "false" value
3052 */
3053 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 GETVAL(value, sub, "value");
3056 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003057 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003058 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003059 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003060 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003061 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 goto error;
3063 }
3064 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003065 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003066 } else if (!strcmp(sub->name, "when")) {
3067 if (anyxml->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003068 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003069 goto error;
3070 }
3071
3072 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003073 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003074 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003075 goto error;
3076 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003077 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 } else if (!strcmp(sub->name, "must")) {
3079 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003080 } else if (!strcmp(sub->name, "if-feature")) {
3081 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003084 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 }
3087 }
Radek Krejci863c2852015-06-03 15:47:11 +02003088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 /* middle part - process nodes with cardinality of 0..n */
3090 if (c_must) {
3091 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003092 if (!anyxml->must) {
3093 LOGMEM;
3094 goto error;
3095 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003097 if (c_ftrs) {
3098 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003099 if (!anyxml->features) {
3100 LOGMEM;
3101 goto error;
3102 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003103 }
Radek Krejci863c2852015-06-03 15:47:11 +02003104
Radek Krejci73adb602015-07-02 18:07:40 +02003105 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003106 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003107 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3108 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003109 if (r) {
3110 goto error;
3111 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003112 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003113 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003114 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003115 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003116 goto error;
3117 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003119 }
Radek Krejci863c2852015-06-03 15:47:11 +02003120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003122
3123error:
3124
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003125 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003128}
3129
Michal Vasko0d343d12015-08-24 14:57:36 +02003130/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003131static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003132read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003133 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003134{
Radek Krejci76512572015-08-04 09:47:08 +02003135 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003136 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003137 struct lyxml_elem *sub, *next;
3138 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003139 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003140 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003143 if (!leaf) {
3144 LOGMEM;
3145 return NULL;
3146 }
Radek Krejci76512572015-08-04 09:47:08 +02003147 leaf->nodetype = LYS_LEAF;
3148 leaf->prev = (struct lys_node *)leaf;
3149 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003150
Michal Vaskoe0c59842015-09-24 13:52:20 +02003151 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3152 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 goto error;
3154 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003155
Radek Krejcia9544502015-08-14 08:24:29 +02003156 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003157
Michal Vasko4f0dad02016-02-15 14:08:23 +01003158 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003159 goto error;
3160 }
3161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003163 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3164 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003165 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003166 continue;
3167 }
3168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003170 if (has_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003171 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 goto error;
3173 }
Michal Vasko88c29542015-11-27 14:57:53 +01003174 /* HACK for unres */
3175 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003176 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003177 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3178 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 goto error;
3180 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003181 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 } else if (!strcmp(sub->name, "default")) {
3183 if (leaf->dflt) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003184 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 goto error;
3186 }
3187 GETVAL(value, sub, "value");
3188 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003189 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 } else if (!strcmp(sub->name, "units")) {
3191 if (leaf->units) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003192 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 goto error;
3194 }
3195 GETVAL(value, sub, "name");
3196 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3197 } else if (!strcmp(sub->name, "mandatory")) {
3198 if (f_mand) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003199 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 goto error;
3201 }
3202 /* just checking the flags in leaf is not sufficient, we would allow
3203 * multiple mandatory statements with the "false" value
3204 */
3205 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 GETVAL(value, sub, "value");
3208 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003209 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003210 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003211 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003212 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003213 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003214 goto error;
3215 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003216 } else if (!strcmp(sub->name, "when")) {
3217 if (leaf->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003218 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003219 goto error;
3220 }
3221
3222 leaf->when = read_yin_when(module, sub);
3223 if (!leaf->when) {
3224 goto error;
3225 }
3226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003227 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003228 c_must++;
3229 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003230 } else if (!strcmp(sub->name, "if-feature")) {
3231 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003235 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003236 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003238
Michal Vasko88c29542015-11-27 14:57:53 +01003239 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003242 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003243 if (!has_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003244 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 goto error;
3246 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003247 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003248 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003249 goto error;
3250 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 /* middle part - process nodes with cardinality of 0..n */
3254 if (c_must) {
3255 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003256 if (!leaf->must) {
3257 LOGMEM;
3258 goto error;
3259 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003261 if (c_ftrs) {
3262 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003263 if (!leaf->features) {
3264 LOGMEM;
3265 goto error;
3266 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003267 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003268
Radek Krejci73adb602015-07-02 18:07:40 +02003269 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003271 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3272 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 if (r) {
3274 goto error;
3275 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003276 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003277 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003278 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003279 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003280 goto error;
3281 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003282 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003286
3287error:
3288
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003289 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003292}
3293
Michal Vasko0d343d12015-08-24 14:57:36 +02003294/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003295static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003296read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003297 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003298{
Radek Krejci76512572015-08-04 09:47:08 +02003299 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003300 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 struct lyxml_elem *sub, *next;
3302 const char *value;
3303 char *endptr;
3304 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003305 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003306 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003310 if (!llist) {
3311 LOGMEM;
3312 return NULL;
3313 }
Radek Krejci76512572015-08-04 09:47:08 +02003314 llist->nodetype = LYS_LEAFLIST;
3315 llist->prev = (struct lys_node *)llist;
3316 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003317
Michal Vaskoe0c59842015-09-24 13:52:20 +02003318 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3319 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 goto error;
3321 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003322
Radek Krejcia9544502015-08-14 08:24:29 +02003323 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003324
Michal Vasko4f0dad02016-02-15 14:08:23 +01003325 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003326 goto error;
3327 }
3328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003330 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3331 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003332 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003333 continue;
3334 }
3335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003337 if (has_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003338 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 goto error;
3340 }
Michal Vasko88c29542015-11-27 14:57:53 +01003341 /* HACK for unres */
3342 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003343 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003344 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3345 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003346 goto error;
3347 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003348 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 } else if (!strcmp(sub->name, "units")) {
3350 if (llist->units) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003351 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
3354 GETVAL(value, sub, "name");
3355 llist->units = lydict_insert(module->ctx, value, strlen(value));
3356 } else if (!strcmp(sub->name, "ordered-by")) {
3357 if (f_ordr) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003358 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 goto error;
3360 }
3361 /* just checking the flags in llist is not sufficient, we would
3362 * allow multiple ordered-by statements with the "system" value
3363 */
3364 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003365
Radek Krejci1574a8d2015-08-03 14:16:52 +02003366 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3368 * state data
3369 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003370 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 continue;
3372 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003374 GETVAL(value, sub, "value");
3375 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003376 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003377 } else if (strcmp(value, "system")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003378 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003380 } /* else system is the default value, so we can ignore it */
3381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 } else if (!strcmp(sub->name, "must")) {
3383 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003384 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003385 } else if (!strcmp(sub->name, "if-feature")) {
3386 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003389 } else if (!strcmp(sub->name, "min-elements")) {
3390 if (f_min) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003391 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003392 goto error;
3393 }
3394 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 GETVAL(value, sub, "value");
3397 while (isspace(value[0])) {
3398 value++;
3399 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 /* convert it to uint32_t */
3402 errno = 0;
3403 endptr = NULL;
3404 val = strtoul(value, &endptr, 10);
3405 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003406 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 goto error;
3408 }
3409 llist->min = (uint32_t) val;
3410 } else if (!strcmp(sub->name, "max-elements")) {
3411 if (f_max) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003412 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003413 goto error;
3414 }
3415 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 GETVAL(value, sub, "value");
3418 while (isspace(value[0])) {
3419 value++;
3420 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003421
Radek Krejci0d7b2472016-02-12 11:11:03 +01003422 if (!strcmp(value, "unbounded")) {
3423 llist->max = 0;
3424 } else {
3425 /* convert it to uint32_t */
3426 errno = 0;
3427 endptr = NULL;
3428 val = strtoul(value, &endptr, 10);
3429 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003430 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003431 goto error;
3432 }
3433 llist->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003435 } else if (!strcmp(sub->name, "when")) {
3436 if (llist->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003437 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003438 goto error;
3439 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003440
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003441 llist->when = read_yin_when(module, sub);
3442 if (!llist->when) {
3443 goto error;
3444 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003445 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003446 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003449
Michal Vasko88c29542015-11-27 14:57:53 +01003450 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003454 if (!has_type) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003455 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
3458 if (llist->max && llist->min > llist->max) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003459 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 goto error;
3461 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 /* middle part - process nodes with cardinality of 0..n */
3464 if (c_must) {
3465 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003466 if (!llist->must) {
3467 LOGMEM;
3468 goto error;
3469 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003470 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003471 if (c_ftrs) {
3472 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003473 if (!llist->features) {
3474 LOGMEM;
3475 goto error;
3476 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003477 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003478
Radek Krejci73adb602015-07-02 18:07:40 +02003479 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003481 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3482 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 if (r) {
3484 goto error;
3485 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003486 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003487 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003488 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003489 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003490 goto error;
3491 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003496
3497error:
3498
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003499 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003502}
3503
Michal Vasko0d343d12015-08-24 14:57:36 +02003504/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003505static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003506read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3507 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003508{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003509 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003510 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003512 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003513 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003515 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003516 char *auxs;
3517 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003519 /* init */
3520 memset(&root, 0, sizeof root);
3521 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003523 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003524 if (!list) {
3525 LOGMEM;
3526 return NULL;
3527 }
Radek Krejci76512572015-08-04 09:47:08 +02003528 list->nodetype = LYS_LIST;
3529 list->prev = (struct lys_node *)list;
3530 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003531
Michal Vaskoe0c59842015-09-24 13:52:20 +02003532 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3533 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 goto error;
3535 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003536
Radek Krejcia9544502015-08-14 08:24:29 +02003537 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 /* process list's specific children */
3540 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003541 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3542 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003543 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003544 continue;
3545 }
3546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 /* data statements */
3548 if (!strcmp(sub->name, "container") ||
3549 !strcmp(sub->name, "leaf-list") ||
3550 !strcmp(sub->name, "leaf") ||
3551 !strcmp(sub->name, "list") ||
3552 !strcmp(sub->name, "choice") ||
3553 !strcmp(sub->name, "uses") ||
3554 !strcmp(sub->name, "grouping") ||
3555 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003556 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003557 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 /* array counters */
3560 } else if (!strcmp(sub->name, "key")) {
3561 /* check cardinality 0..1 */
3562 if (list->keys_size) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003563 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 goto error;
3565 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 /* count the number of keys */
3568 GETVAL(value, sub, "value");
3569 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003570 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 while ((value = strpbrk(value, " \t\n"))) {
3572 list->keys_size++;
3573 while (isspace(*value)) {
3574 value++;
3575 }
3576 }
3577 list->keys_size++;
3578 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003579 if (!list->keys) {
3580 LOGMEM;
3581 goto error;
3582 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003583 } else if (!strcmp(sub->name, "unique")) {
3584 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003585 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003586 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 } else if (!strcmp(sub->name, "typedef")) {
3588 c_tpdf++;
3589 } else if (!strcmp(sub->name, "must")) {
3590 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003591 } else if (!strcmp(sub->name, "if-feature")) {
3592 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003594 /* optional stetments */
3595 } else if (!strcmp(sub->name, "ordered-by")) {
3596 if (f_ordr) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003597 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003598 goto error;
3599 }
3600 /* just checking the flags in llist is not sufficient, we would
3601 * allow multiple ordered-by statements with the "system" value
3602 */
3603 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003604
Radek Krejci1574a8d2015-08-03 14:16:52 +02003605 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3607 * state data
3608 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003609 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 continue;
3611 }
Radek Krejci345ad742015-06-03 11:04:18 +02003612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 GETVAL(value, sub, "value");
3614 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003615 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 } else if (strcmp(value, "system")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003617 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 goto error;
3619 }
3620 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003621 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 } else if (!strcmp(sub->name, "min-elements")) {
3623 if (f_min) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003624 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 goto error;
3626 }
3627 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003629 GETVAL(value, sub, "value");
3630 while (isspace(value[0])) {
3631 value++;
3632 }
Radek Krejci345ad742015-06-03 11:04:18 +02003633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003634 /* convert it to uint32_t */
3635 errno = 0;
3636 auxs = NULL;
3637 val = strtoul(value, &auxs, 10);
3638 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003639 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640 goto error;
3641 }
3642 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003643 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003644 } else if (!strcmp(sub->name, "max-elements")) {
3645 if (f_max) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003646 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 goto error;
3648 }
3649 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003650
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 GETVAL(value, sub, "value");
3652 while (isspace(value[0])) {
3653 value++;
3654 }
Radek Krejci345ad742015-06-03 11:04:18 +02003655
Radek Krejci0d7b2472016-02-12 11:11:03 +01003656 if (!strcmp(value, "unbounded")) {
3657 list->max = 0;;
3658 } else {
3659 /* convert it to uint32_t */
3660 errno = 0;
3661 auxs = NULL;
3662 val = strtoul(value, &auxs, 10);
3663 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003664 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003665 goto error;
3666 }
3667 list->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003669 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003670 } else if (!strcmp(sub->name, "when")) {
3671 if (list->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003672 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003673 goto error;
3674 }
3675
3676 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003677 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003678 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003679 goto error;
3680 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003681 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003682 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003683 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003684 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 }
3686 }
Radek Krejci345ad742015-06-03 11:04:18 +02003687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003689 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003690 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 goto error;
3692 }
3693 if (list->max && list->min > list->max) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003694 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 goto error;
3696 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3699 if (c_tpdf) {
3700 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003701 if (!list->tpdf) {
3702 LOGMEM;
3703 goto error;
3704 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003706 if (c_must) {
3707 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003708 if (!list->must) {
3709 LOGMEM;
3710 goto error;
3711 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003712 }
3713 if (c_ftrs) {
3714 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003715 if (!list->features) {
3716 LOGMEM;
3717 goto error;
3718 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003719 }
Radek Krejci73adb602015-07-02 18:07:40 +02003720 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003722 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3723 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 if (r) {
3725 goto error;
3726 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003727 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003728 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003729 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003730 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003731 goto error;
3732 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003733 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003734 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3735 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003736 if (r) {
3737 goto error;
3738 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 }
3740 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003741
Michal Vasko4f0dad02016-02-15 14:08:23 +01003742 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003743 goto error;
3744 }
3745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 /* last part - process data nodes */
3747 LY_TREE_FOR_SAFE(root.child, next, sub) {
3748 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003749 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003750 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003751 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003753 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003755 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003757 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003759 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003761 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003763 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003764 } else {
3765 LOGINT;
3766 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003768 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 goto error;
3770 }
Radek Krejci73adb602015-07-02 18:07:40 +02003771
Michal Vasko345da0a2015-12-02 10:35:55 +01003772 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003774
Radek Krejci461efb92016-02-12 15:52:18 +01003775 if (key_str) {
3776 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
3777 goto error;
3778 }
3779 } /* 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 +02003780
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003781 /* process unique statements */
3782 if (c_uniq) {
3783 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003784 if (!list->unique) {
3785 LOGMEM;
3786 goto error;
3787 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003788
Radek Krejci461efb92016-02-12 15:52:18 +01003789 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3790 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3791 list->unique_size++;
3792 if (r) {
3793 goto error;
3794 }
3795
3796 lyxml_free(module->ctx, sub);
3797 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003801
3802error:
3803
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003804 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003806 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 }
3808 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003809 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003813}
3814
Michal Vasko0d343d12015-08-24 14:57:36 +02003815/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003816static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003817read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3818 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003819{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003821 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003822 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003823 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 const char *value;
3825 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003826 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 /* init */
3829 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003832 if (!cont) {
3833 LOGMEM;
3834 return NULL;
3835 }
Radek Krejci76512572015-08-04 09:47:08 +02003836 cont->nodetype = LYS_CONTAINER;
3837 cont->prev = (struct lys_node *)cont;
3838 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003839
Michal Vaskoe0c59842015-09-24 13:52:20 +02003840 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3841 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003842 goto error;
3843 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003844
Radek Krejcia9544502015-08-14 08:24:29 +02003845 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 /* process container's specific children */
3848 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003849 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003850 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003851 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003852 continue;
3853 }
3854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 if (!strcmp(sub->name, "presence")) {
3856 if (cont->presence) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003857 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 goto error;
3859 }
3860 GETVAL(value, sub, "value");
3861 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003862
Michal Vasko345da0a2015-12-02 10:35:55 +01003863 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003864 } else if (!strcmp(sub->name, "when")) {
3865 if (cont->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003866 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003867 goto error;
3868 }
3869
3870 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003871 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003872 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003873 goto error;
3874 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003875 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 /* data statements */
3878 } else if (!strcmp(sub->name, "container") ||
3879 !strcmp(sub->name, "leaf-list") ||
3880 !strcmp(sub->name, "leaf") ||
3881 !strcmp(sub->name, "list") ||
3882 !strcmp(sub->name, "choice") ||
3883 !strcmp(sub->name, "uses") ||
3884 !strcmp(sub->name, "grouping") ||
3885 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003886 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003887 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 /* array counters */
3890 } else if (!strcmp(sub->name, "typedef")) {
3891 c_tpdf++;
3892 } else if (!strcmp(sub->name, "must")) {
3893 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003894 } else if (!strcmp(sub->name, "if-feature")) {
3895 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01003897 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003898 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 }
3900 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3903 if (c_tpdf) {
3904 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003905 if (!cont->tpdf) {
3906 LOGMEM;
3907 goto error;
3908 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003909 }
3910 if (c_must) {
3911 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003912 if (!cont->must) {
3913 LOGMEM;
3914 goto error;
3915 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003916 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003917 if (c_ftrs) {
3918 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003919 if (!cont->features) {
3920 LOGMEM;
3921 goto error;
3922 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003923 }
Radek Krejci800af702015-06-02 13:46:01 +02003924
Radek Krejci73adb602015-07-02 18:07:40 +02003925 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003927 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3928 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 if (r) {
3930 goto error;
3931 }
3932 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003933 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3934 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 if (r) {
3936 goto error;
3937 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003938 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003939 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003940 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003941 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003942 goto error;
3943 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003946
Michal Vasko4f0dad02016-02-15 14:08:23 +01003947 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003948 goto error;
3949 }
3950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 /* last part - process data nodes */
3952 LY_TREE_FOR_SAFE(root.child, next, sub) {
3953 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003958 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003964 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003966 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003967 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003970 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 goto error;
3972 }
Radek Krejci73adb602015-07-02 18:07:40 +02003973
Michal Vasko345da0a2015-12-02 10:35:55 +01003974 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003978
3979error:
3980
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003981 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003982 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003983 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003984 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003987}
3988
Michal Vasko0d343d12015-08-24 14:57:36 +02003989/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003990static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003991read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003992 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003993{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003994 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003995 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003996 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003997 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 int r;
3999 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 /* init */
4002 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004005 if (!grp) {
4006 LOGMEM;
4007 return NULL;
4008 }
Radek Krejci76512572015-08-04 09:47:08 +02004009 grp->nodetype = LYS_GROUPING;
4010 grp->prev = (struct lys_node *)grp;
4011 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004012
Michal Vasko71e1aa82015-08-12 12:17:51 +02004013 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004014 goto error;
4015 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004016
Radek Krejcia9544502015-08-14 08:24:29 +02004017 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4018
Radek Krejci1d82ef62015-08-07 14:44:40 +02004019 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004020 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4021 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004022 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004023 continue;
4024 }
4025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 /* data statements */
4027 if (!strcmp(sub->name, "container") ||
4028 !strcmp(sub->name, "leaf-list") ||
4029 !strcmp(sub->name, "leaf") ||
4030 !strcmp(sub->name, "list") ||
4031 !strcmp(sub->name, "choice") ||
4032 !strcmp(sub->name, "uses") ||
4033 !strcmp(sub->name, "grouping") ||
4034 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004035 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004036 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004038 /* array counters */
4039 } else if (!strcmp(sub->name, "typedef")) {
4040 c_tpdf++;
4041 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004042 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 goto error;
4044 }
4045 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4048 if (c_tpdf) {
4049 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004050 if (!grp->tpdf) {
4051 LOGMEM;
4052 goto error;
4053 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004055 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004056 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4057 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004058 if (r) {
4059 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004060 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004062
Michal Vasko4f0dad02016-02-15 14:08:23 +01004063 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004064 goto error;
4065 }
4066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004067 /* last part - process data nodes */
4068 LY_TREE_FOR_SAFE(root.child, next, sub) {
4069 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004070 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004071 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004072 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004073 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004074 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004075 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004076 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004077 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004078 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004079 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004081 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004083 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004084 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004085 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004086 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004087 goto error;
4088 }
Radek Krejci73adb602015-07-02 18:07:40 +02004089
Michal Vasko345da0a2015-12-02 10:35:55 +01004090 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004093 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004094
4095error:
4096
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004097 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004098 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004099 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004100 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004102 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004103}
4104
Michal Vasko0d343d12015-08-24 14:57:36 +02004105/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004106static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004107read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4108 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004109{
Radek Krejcie0674f82015-06-15 13:58:51 +02004110 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004111 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004112 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004113 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004114 int r;
4115 int c_tpdf = 0;
4116
Radek Krejcie0674f82015-06-15 13:58:51 +02004117 /* init */
4118 memset(&root, 0, sizeof root);
4119
Michal Vasko38d01f72015-06-15 09:41:06 +02004120 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004121 if (!inout) {
4122 LOGMEM;
4123 return NULL;
4124 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004125 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004126
4127 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004128 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004129 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004130 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004132 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004133 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004134 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004135 }
4136
Radek Krejci76512572015-08-04 09:47:08 +02004137 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004138
Radek Krejci6a113852015-07-03 16:04:20 +02004139 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004140 goto error;
4141 }
4142
Radek Krejcia9544502015-08-14 08:24:29 +02004143 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4144
Michal Vasko38d01f72015-06-15 09:41:06 +02004145 /* data statements */
4146 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004147 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4148 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004149 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004150 continue;
4151 }
4152
Michal Vasko38d01f72015-06-15 09:41:06 +02004153 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 !strcmp(sub->name, "leaf-list") ||
4155 !strcmp(sub->name, "leaf") ||
4156 !strcmp(sub->name, "list") ||
4157 !strcmp(sub->name, "choice") ||
4158 !strcmp(sub->name, "uses") ||
4159 !strcmp(sub->name, "grouping") ||
4160 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004161 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004162 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004164 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004165 } else if (!strcmp(sub->name, "typedef")) {
4166 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004167
Michal Vasko38d01f72015-06-15 09:41:06 +02004168 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004169 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004171 }
4172 }
4173
4174 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4175 if (c_tpdf) {
4176 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004177 if (!inout->tpdf) {
4178 LOGMEM;
4179 goto error;
4180 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004181 }
4182
Radek Krejci73adb602015-07-02 18:07:40 +02004183 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004184 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4185 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004186 if (r) {
4187 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004188 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004189 }
4190
Michal Vasko4f0dad02016-02-15 14:08:23 +01004191 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004192 goto error;
4193 }
4194
Michal Vasko38d01f72015-06-15 09:41:06 +02004195 /* last part - process data nodes */
4196 LY_TREE_FOR_SAFE(root.child, next, sub) {
4197 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004198 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004199 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004200 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004201 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004202 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004203 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004204 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004205 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004206 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004207 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004208 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004209 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004210 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004211 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004212 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004213 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004215 goto error;
4216 }
Radek Krejci73adb602015-07-02 18:07:40 +02004217
Michal Vasko345da0a2015-12-02 10:35:55 +01004218 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004219 }
4220
Michal Vasko38d01f72015-06-15 09:41:06 +02004221 return retval;
4222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004223error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004224
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004225 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004226 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004227 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004228 }
4229
4230 return NULL;
4231}
4232
Michal Vasko0d343d12015-08-24 14:57:36 +02004233/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004234static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004235read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4236 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004237{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004238 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004239 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004240 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004241 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004243 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004244
Michal Vaskoc6551b32015-06-16 10:51:43 +02004245 memset(&root, 0, sizeof root);
4246
Michal Vasko0ea41032015-06-16 08:53:55 +02004247 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004248 if (!notif) {
4249 LOGMEM;
4250 return NULL;
4251 }
Radek Krejci76512572015-08-04 09:47:08 +02004252 notif->nodetype = LYS_NOTIF;
4253 notif->prev = (struct lys_node *)notif;
4254 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004255
Radek Krejci6a113852015-07-03 16:04:20 +02004256 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004257 goto error;
4258 }
4259
Radek Krejcia9544502015-08-14 08:24:29 +02004260 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4261
Michal Vasko0ea41032015-06-16 08:53:55 +02004262 /* process rpc's specific children */
4263 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004264 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4265 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004266 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004267 continue;
4268 }
4269
Michal Vasko0ea41032015-06-16 08:53:55 +02004270 /* data statements */
4271 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004272 !strcmp(sub->name, "leaf-list") ||
4273 !strcmp(sub->name, "leaf") ||
4274 !strcmp(sub->name, "list") ||
4275 !strcmp(sub->name, "choice") ||
4276 !strcmp(sub->name, "uses") ||
4277 !strcmp(sub->name, "grouping") ||
4278 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004279 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004280 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004283 } else if (!strcmp(sub->name, "typedef")) {
4284 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004285 } else if (!strcmp(sub->name, "if-feature")) {
4286 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004287 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004288 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004289 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004290 }
4291 }
4292
4293 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4294 if (c_tpdf) {
4295 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004296 if (!notif->tpdf) {
4297 LOGMEM;
4298 goto error;
4299 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004300 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004301 if (c_ftrs) {
4302 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004303 if (!notif->features) {
4304 LOGMEM;
4305 goto error;
4306 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004307 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004308
Radek Krejci73adb602015-07-02 18:07:40 +02004309 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004310 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004311 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4312 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004313 if (r) {
4314 goto error;
4315 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004316 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004317 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004318 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004319 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004320 goto error;
4321 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004322 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004323 }
4324
Michal Vasko4f0dad02016-02-15 14:08:23 +01004325 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004326 goto error;
4327 }
4328
Michal Vasko0ea41032015-06-16 08:53:55 +02004329 /* last part - process data nodes */
4330 LY_TREE_FOR_SAFE(root.child, next, sub) {
4331 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004332 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004333 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004334 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004335 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004336 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004337 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004338 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004339 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004340 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004341 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004342 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004343 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004344 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004345 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004346 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004347 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004348 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004349 goto error;
4350 }
Radek Krejci73adb602015-07-02 18:07:40 +02004351
Michal Vasko345da0a2015-12-02 10:35:55 +01004352 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004353 }
4354
Michal Vasko0ea41032015-06-16 08:53:55 +02004355 return retval;
4356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004358
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004359 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004360 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004361 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004362 }
4363
4364 return NULL;
4365}
4366
Michal Vasko0d343d12015-08-24 14:57:36 +02004367/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004368static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004369read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4370 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004371{
Radek Krejcie0674f82015-06-15 13:58:51 +02004372 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004373 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004374 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004375 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004376 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004377 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004378
Radek Krejcie0674f82015-06-15 13:58:51 +02004379 /* init */
4380 memset(&root, 0, sizeof root);
4381
Michal Vasko38d01f72015-06-15 09:41:06 +02004382 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004383 if (!rpc) {
4384 LOGMEM;
4385 return NULL;
4386 }
Radek Krejci76512572015-08-04 09:47:08 +02004387 rpc->nodetype = LYS_RPC;
4388 rpc->prev = (struct lys_node *)rpc;
4389 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004390
Radek Krejci6a113852015-07-03 16:04:20 +02004391 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004392 goto error;
4393 }
4394
Radek Krejcia9544502015-08-14 08:24:29 +02004395 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4396
Michal Vasko38d01f72015-06-15 09:41:06 +02004397 /* process rpc's specific children */
4398 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004399 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4400 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004401 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004402 continue;
4403 }
4404
Michal Vasko38d01f72015-06-15 09:41:06 +02004405 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004406 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004407 && (rpc->child->nodetype == LYS_INPUT
4408 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004409 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004410 goto error;
4411 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004412 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004413 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004414 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004416 && (rpc->child->nodetype == LYS_INPUT
4417 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004418 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004419 goto error;
4420 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004421 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004422 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004424 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004425 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004426 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004427 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004430 } else if (!strcmp(sub->name, "typedef")) {
4431 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004432 } else if (!strcmp(sub->name, "if-feature")) {
4433 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004434 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004435 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004436 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004437 }
4438 }
4439
4440 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4441 if (c_tpdf) {
4442 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004443 if (!rpc->tpdf) {
4444 LOGMEM;
4445 goto error;
4446 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004447 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004448 if (c_ftrs) {
4449 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004450 if (!rpc->features) {
4451 LOGMEM;
4452 goto error;
4453 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004454 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004455
Radek Krejci73adb602015-07-02 18:07:40 +02004456 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004457 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004458 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4459 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004460 if (r) {
4461 goto error;
4462 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004463 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004464 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004465 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004466 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004467 goto error;
4468 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004469 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004470 }
4471
Michal Vasko4f0dad02016-02-15 14:08:23 +01004472 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004473 goto error;
4474 }
4475
Michal Vasko38d01f72015-06-15 09:41:06 +02004476 /* last part - process data nodes */
4477 LY_TREE_FOR_SAFE(root.child, next, sub) {
4478 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004479 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004480 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004481 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004482 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004483 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004484 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004485 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004486 goto error;
4487 }
Radek Krejci73adb602015-07-02 18:07:40 +02004488
Michal Vasko345da0a2015-12-02 10:35:55 +01004489 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004490 }
4491
Michal Vasko38d01f72015-06-15 09:41:06 +02004492 return retval;
4493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004495
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004496 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004497 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004498 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004499 }
4500
4501 return NULL;
4502}
4503
Michal Vasko0d343d12015-08-24 14:57:36 +02004504/* logs directly
4505 *
Radek Krejci74705112015-06-05 10:25:44 +02004506 * resolve - referenced grouping should be bounded to the namespace (resolved)
4507 * only when uses does not appear in grouping. In a case of grouping's uses,
4508 * we just get information but we do not apply augment or refine to it.
4509 */
Radek Krejci76512572015-08-04 09:47:08 +02004510static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004511read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004512 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004513{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004515 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004516 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004518 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004522 if (!uses) {
4523 LOGMEM;
4524 return NULL;
4525 }
Radek Krejci76512572015-08-04 09:47:08 +02004526 uses->nodetype = LYS_USES;
4527 uses->prev = (struct lys_node *)uses;
4528 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004529
Radek Krejcia9544502015-08-14 08:24:29 +02004530 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004532
Michal Vaskoe0c59842015-09-24 13:52:20 +02004533 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4534 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 goto error;
4536 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004537
Radek Krejcia9544502015-08-14 08:24:29 +02004538 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004541 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004542 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4543 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004544 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004545 continue;
4546 }
4547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004548 if (!strcmp(sub->name, "refine")) {
4549 c_ref++;
4550 } else if (!strcmp(sub->name, "augment")) {
4551 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004552 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004553 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004554 } else if (!strcmp(sub->name, "when")) {
4555 if (uses->when) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004556 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004557 goto error;
4558 }
4559
4560 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004561 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004562 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004563 goto error;
4564 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004565 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004567 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 }
4570 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 /* process properties with cardinality 0..n */
4573 if (c_ref) {
4574 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004575 if (!uses->refine) {
4576 LOGMEM;
4577 goto error;
4578 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 }
4580 if (c_aug) {
4581 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004582 if (!uses->augment) {
4583 LOGMEM;
4584 goto error;
4585 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004587 if (c_ftrs) {
4588 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004589 if (!uses->features) {
4590 LOGMEM;
4591 goto error;
4592 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004593 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004594
Michal Vasko4f0dad02016-02-15 14:08:23 +01004595 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004596 goto error;
4597 }
4598
Radek Krejcia9544502015-08-14 08:24:29 +02004599 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004601 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4602 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004603 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004604 goto error;
4605 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004606 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004607 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4608 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004609 if (r) {
4610 goto error;
4611 }
4612 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004613 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004614 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004615 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004616 goto error;
4617 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 }
4619 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004620
Michal Vasko0bd29d12015-08-19 11:45:49 +02004621 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004622 goto error;
4623 }
Radek Krejci74705112015-06-05 10:25:44 +02004624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 if (resolve) {
4626 /* inherit config flag */
4627 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004628 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 } else {
4630 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004631 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 }
4633 }
Radek Krejcib388c152015-06-04 17:03:03 +02004634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004636
4637error:
4638
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004639 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004642}
4643
Michal Vasko0d343d12015-08-24 14:57:36 +02004644/* logs directly
4645 *
4646 * common code for yin_read_module() and yin_read_submodule()
4647 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648static int
Radek Krejcic071c542016-01-27 14:57:51 +01004649read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4650 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004651{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004653 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004654 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004655 struct lys_module *trg;
4656 struct lys_import *aux_imp;
4657 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004659 int i, j, r;
4660 int inc_size_aux = 0;
4661 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004662 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004663 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;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004664
Radek Krejcic071c542016-01-27 14:57:51 +01004665 /* to simplify code, store the module/submodule being processed as trg */
4666 trg = submodule ? (struct lys_module*)submodule : module;
4667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 /* init */
4669 memset(&root, 0, sizeof root);
4670 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004671 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 /*
4674 * in the first run, we process elements with cardinality of 1 or 0..1 and
4675 * count elements with cardinality 0..n. Data elements (choices, containers,
4676 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4677 * need have all top-level and groupings already prepared at that time. In
4678 * the middle loop, we process other elements with carinality of 0..n since
4679 * we need to allocate arrays to store them.
4680 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004681 LY_TREE_FOR_SAFE(yin->child, next, child) {
4682 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004683 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004684 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 continue;
4686 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004687
Radek Krejcic071c542016-01-27 14:57:51 +01004688 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 if (module->ns) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004690 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 goto error;
4692 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004693 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004695 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004696 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 if (module->prefix) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004698 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 goto error;
4700 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004702 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004703 goto error;
4704 }
4705 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004706 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004707 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4708 if (submodule->prefix) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004709 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 goto error;
4711 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004713 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004714 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004715 goto error;
4716 }
Radek Krejcif3886932015-06-04 17:36:06 +02004717
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004719 if (!child->child) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004720 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004722 } else if (strcmp(child->child->name, "prefix")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004723 LOGVAL(LYE_INSTMT, LOGLINE(child->child), LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004725 } else if (child->child->next) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004726 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01004727 child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 goto error;
4729 }
4730 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004731 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 /* check here differs from a generic prefix check, since this prefix
4733 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004734 */
Radek Krejcic6556022016-01-27 15:16:45 +01004735 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 goto error;
4737 }
Radek Krejcic071c542016-01-27 14:57:51 +01004738 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004741 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004742
4743 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004744 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004746 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004748 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004750 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004752 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004754 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004755 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004756 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004757 lyxml_unlink_elem(ctx, child, 2);
4758 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004759
Radek Krejci1d82ef62015-08-07 14:44:40 +02004760 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004761 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004762 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004763 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004766 } else if (!strcmp(child->name, "container") ||
4767 !strcmp(child->name, "leaf-list") ||
4768 !strcmp(child->name, "leaf") ||
4769 !strcmp(child->name, "list") ||
4770 !strcmp(child->name, "choice") ||
4771 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004772 !strcmp(child->name, "anyxml") ||
4773 !strcmp(child->name, "rpc") ||
4774 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004775 lyxml_unlink_elem(ctx, child, 2);
4776 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004777
Radek Krejci1d82ef62015-08-07 14:44:40 +02004778 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004779 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004780 lyxml_unlink_elem(ctx, child, 2);
4781 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004783 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004784 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004785 if (trg->dsc) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004786 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 goto error;
4788 }
Radek Krejcic071c542016-01-27 14:57:51 +01004789 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004790 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004791 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004792 goto error;
4793 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004794 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004795 if (trg->ref) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004796 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 goto error;
4798 }
Radek Krejcic071c542016-01-27 14:57:51 +01004799 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004800 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004801 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 goto error;
4803 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004804 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004805 if (trg->org) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004806 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004807 goto error;
4808 }
Radek Krejcic071c542016-01-27 14:57:51 +01004809 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004810 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004811 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 goto error;
4813 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004814 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004815 if (trg->contact) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004816 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 goto error;
4818 }
Radek Krejcic071c542016-01-27 14:57:51 +01004819 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004820 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004821 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 goto error;
4823 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004824 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004825 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004826 if (version_flag) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004827 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004828 goto error;
4829 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004830 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004831 if (strcmp(value, "1")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004832 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 goto error;
4834 }
Radek Krejcic071c542016-01-27 14:57:51 +01004835 version_flag = 1;
4836 if (!submodule) {
4837 module->version = 1;
4838 } /* TODO else check for the submodule's same version as in main module, waits for YANG 1.1 support */
Michal Vasko345da0a2015-12-02 10:35:55 +01004839 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004840
Radek Krejci1d82ef62015-08-07 14:44:40 +02004841 } else if (!strcmp(child->name, "extension")) {
4842 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004843
Radek Krejci3d468122015-10-02 13:36:12 +02004844 /* we have the following supported (hardcoded) extensions: */
4845 /* ietf-netconf's get-filter-element-attributes */
4846 if (!strcmp(module->ns, LY_NSNC) &&
4847 !strcmp(value, "get-filter-element-attributes")) {
4848 LOGDBG("NETCONF filter extension found");
4849 /* NACM's default-deny-write and default-deny-all */
4850 } else if (!strcmp(module->ns, LY_NSNACM) &&
4851 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4852 LOGDBG("NACM extension found");
4853 /* other extensions are not supported, so inform about such an extension */
4854 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004855 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004856 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004857 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004858 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004859 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 }
4862 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004863
Radek Krejcic071c542016-01-27 14:57:51 +01004864 /* check for mandatory statements */
4865 if (submodule && !submodule->prefix) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004866 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004867 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004868 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 if (!module->ns) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004870 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 goto error;
4872 }
4873 if (!module->prefix) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004874 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 goto error;
4876 }
4877 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 /* allocate arrays for elements with cardinality of 0..n */
4880 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004881 trg->imp = calloc(c_imp, sizeof *trg->imp);
4882 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004883 LOGMEM;
4884 goto error;
4885 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004886 }
4887 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004888 trg->rev = calloc(c_rev, sizeof *trg->rev);
4889 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004890 LOGMEM;
4891 goto error;
4892 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004893 }
4894 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004895 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4896 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004897 LOGMEM;
4898 goto error;
4899 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004900 }
4901 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004902 trg->ident = calloc(c_ident, sizeof *trg->ident);
4903 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004904 LOGMEM;
4905 goto error;
4906 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004907 }
4908 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004909 trg->inc = calloc(c_inc, sizeof *trg->inc);
4910 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004911 LOGMEM;
4912 goto error;
4913 }
Radek Krejcic071c542016-01-27 14:57:51 +01004914 trg->inc_size = c_inc;
4915 /* trg->inc_size can be updated by the included submodules,
4916 * so we will use inc_size_aux here, trg->inc_size stores the
4917 * target size of the array
4918 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004920 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004921 trg->augment = calloc(c_aug, sizeof *trg->augment);
4922 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004923 LOGMEM;
4924 goto error;
4925 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004926 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004927 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004928 trg->features = calloc(c_ftrs, sizeof *trg->features);
4929 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004930 LOGMEM;
4931 goto error;
4932 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004933 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004934 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004935 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4936 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004937 LOGMEM;
4938 goto error;
4939 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004940 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004941
Michal Vasko2f7925f2015-10-21 15:06:56 +02004942 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4943 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004944 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004945 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4946 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 if (r) {
4948 goto error;
4949 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004951 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004952 for (i = 0; i < trg->imp_size - 1; i++) {
4953 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004954 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 goto error;
4956 }
4957 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004958
Radek Krejci1d82ef62015-08-07 14:44:40 +02004959 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004960 memset(&inc, 0, sizeof inc);
4961 /* 1) pass module, not trg, since we want to pass the main module
4962 * 2) we cannot pass directly the structure in the array since
4963 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004964 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004965 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4966 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 if (r) {
4968 goto error;
4969 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004972 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004973 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004974 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.",
Michal Vasko27ab8222016-02-12 09:33:52 +01004975 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 goto error;
4977 }
4978 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004979
Radek Krejci1d82ef62015-08-07 14:44:40 +02004980 } else if (!strcmp(child->name, "revision")) {
4981 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004982 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 goto error;
4984 }
Radek Krejcic071c542016-01-27 14:57:51 +01004985 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004987 for (i = 0; i < trg->rev_size; i++) {
4988 if (!strcmp(value, trg->rev[i].date)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004989 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, value, child->name);
Radek Krejciadb57612016-02-16 13:34:34 +01004990 LOGVAL(LYE_SPEC, 0, 0, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 }
4992 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004993
Radek Krejci1d82ef62015-08-07 14:44:40 +02004994 LY_TREE_FOR(child->child, child2) {
4995 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004996 if (trg->rev[trg->rev_size].dsc) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01004997 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004998 goto error;
4999 }
Radek Krejcic071c542016-01-27 14:57:51 +01005000 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5001 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005002 goto error;
5003 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005004 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005005 if (trg->rev[trg->rev_size].ref) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01005006 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 goto error;
5008 }
Radek Krejcic071c542016-01-27 14:57:51 +01005009 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5010 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005011 goto error;
5012 }
5013 } else {
Michal Vaskoe5e06292016-02-26 09:56:41 +01005014 LOGVAL(LYE_INSTMT, LOGLINE(child2), LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005015 goto error;
5016 }
5017 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005020 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005022 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005023 if (!value) {
5024 LOGMEM;
5025 goto error;
5026 }
Radek Krejcic071c542016-01-27 14:57:51 +01005027 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5028 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005029 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005030
Radek Krejci749190d2016-02-18 16:26:25 +01005031 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005032 value = trg->rev[0].dsc;
5033 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5034 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005036
Radek Krejci749190d2016-02-18 16:26:25 +01005037 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005038 value = trg->rev[0].ref;
5039 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5040 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005041 }
5042 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005043
Radek Krejcic071c542016-01-27 14:57:51 +01005044 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005045
Radek Krejci1d82ef62015-08-07 14:44:40 +02005046 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005047 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5048 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 if (r) {
5050 goto error;
5051 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005052
Radek Krejci1d82ef62015-08-07 14:44:40 +02005053 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005054 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5055 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005056 if (r) {
5057 goto error;
5058 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005059
Radek Krejci1d82ef62015-08-07 14:44:40 +02005060 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005061 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5062 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005063 if (r) {
5064 goto error;
5065 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005066
Radek Krejci1d82ef62015-08-07 14:44:40 +02005067 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005068 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5069 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005070 if (r) {
5071 goto error;
5072 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005073 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5074 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005076 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005077 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005078
Radek Krejcic071c542016-01-27 14:57:51 +01005079 if (submodule) {
5080 /* propagate imports into the main module */
5081 for (i = r = 0; i < submodule->imp_size; i++) {
5082 for (j = 0; j < module->imp_size; j++) {
5083 if (submodule->imp[i].module == module->imp[j].module &&
5084 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5085 /* check prefix match */
Radek Krejci749190d2016-02-18 16:26:25 +01005086 if (!ly_strequal(submodule->imp[i].prefix, module->imp[j].prefix, 1)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01005087 LOGVAL(LYE_INID, LOGLINE(yin), LY_VLOG_NONE, NULL, submodule->imp[i].prefix,
Radek Krejcic071c542016-01-27 14:57:51 +01005088 "non-matching prefixes of imported module in main module and submodule");
5089 goto error;
5090 }
5091 break;
5092 }
5093 }
5094 if (j == module->imp_size) {
5095 /* new import */
5096 r++;
5097 }
5098 }
5099 if (r) {
5100 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5101 if (!aux_imp) {
5102 LOGMEM;
5103 goto error;
5104 }
5105 module->imp = aux_imp;
5106 for (i = r = 0; i < submodule->imp_size; i++) {
5107 for (j = 0; j < module->imp_size; j++) {
5108 if (submodule->imp[i].module == module->imp[j].module) {
5109 break;
5110 }
5111 }
5112 if (j == module->imp_size) {
5113 /* new import */
5114 /* check prefix uniqueness */
5115 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01005116 LOGVAL(LYE_DUPID, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", submodule->imp[i].prefix);
Radek Krejcic071c542016-01-27 14:57:51 +01005117 goto error;
5118 }
5119 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5120 module->imp[module->imp_size + r].external = 1;
5121 r++;
5122 }
5123 }
5124 module->imp_size += r;
5125 }
5126
Michal Vaskoe2905632016-02-11 15:42:24 +01005127 /* propagate includes into the main module */
Radek Krejcic071c542016-01-27 14:57:51 +01005128 for (i = r = 0; i < submodule->inc_size; i++) {
5129 for (j = 0; j < module->inc_size; j++) {
5130 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5131 break;
5132 }
5133 }
5134 if (j == module->inc_size) {
5135 /* new include */
5136 r++;
5137 }
5138 }
5139
5140 if (r) {
5141 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5142 if (!aux_inc) {
5143 LOGMEM;
5144 goto error;
5145 }
5146 module->inc = aux_inc;
5147 for (i = r = 0; i < submodule->inc_size; i++) {
5148 for (j = 0; j < module->inc_size; j++) {
5149 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5150 break;
5151 }
5152 }
5153 if (j == module->inc_size) {
5154 /* new include */
5155 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5156 module->inc[module->inc_size + r].external = 1;
5157 r++;
5158 }
5159 }
5160 module->inc_size += r;
5161 }
5162 }
5163
Radek Krejcif5be10f2015-06-16 13:29:36 +02005164 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005165 * refer to them. Submodule's data nodes are stored in the
5166 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005168 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005169 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005170 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 goto error;
5172 }
Radek Krejci74705112015-06-05 10:25:44 +02005173
Michal Vasko345da0a2015-12-02 10:35:55 +01005174 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005175 }
Radek Krejci74705112015-06-05 10:25:44 +02005176
Radek Krejcif5be10f2015-06-16 13:29:36 +02005177 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005178 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005179
Radek Krejci1d82ef62015-08-07 14:44:40 +02005180 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005181 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005182 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005183 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005184 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005185 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005186 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005187 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005188 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005189 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005190 } else if (!strcmp(child->name, "uses")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005191 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005192 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005193 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005194 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005195 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005196 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005197 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005198 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005199 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 goto error;
5201 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005202
Michal Vasko345da0a2015-12-02 10:35:55 +01005203 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005205
Michal Vasko2f7925f2015-10-21 15:06:56 +02005206 /* ... and finally augments (last, so we can augment our data, for instance) */
5207 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005208 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5209 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005210
Michal Vasko2f7925f2015-10-21 15:06:56 +02005211 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005212 goto error;
5213 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005214 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005215 }
5216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005218
5219error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 /* cleanup */
5221 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005222 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 }
5224 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005225 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005226 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005227 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005228 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005229 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005231 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005232}
5233
Michal Vasko0d343d12015-08-24 14:57:36 +02005234/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005235struct lys_submodule *
5236yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005237{
Michal Vasko9f258e42016-02-11 11:36:27 +01005238 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005239 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005240 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005241 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005242 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005243
Michal Vasko5a721fd2016-02-16 12:16:48 +01005244 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005245
Radek Krejci722b0072016-02-01 17:09:45 +01005246 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005248 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005251 /* check root element */
5252 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01005253 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 goto error;
5255 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005258 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 goto error;
5260 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005261
Michal Vasko5a721fd2016-02-16 12:16:48 +01005262 submodule = calloc(1, sizeof *submodule);
5263 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 LOGMEM;
5265 goto error;
5266 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005267
Michal Vasko5a721fd2016-02-16 12:16:48 +01005268 submodule->ctx = module->ctx;
5269 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5270 submodule->type = 1;
5271 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005272
Michal Vasko5a721fd2016-02-16 12:16:48 +01005273 LOGVRB("Reading submodule \"%s\".", submodule->name);
5274 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005275 goto error;
5276 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005279 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005280
Michal Vasko5a721fd2016-02-16 12:16:48 +01005281 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005282
Michal Vasko5a721fd2016-02-16 12:16:48 +01005283 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005284
5285error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005287 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005288 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005289
Michal Vasko5a721fd2016-02-16 12:16:48 +01005290 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005291 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005292 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005293 }
5294
Michal Vasko5a721fd2016-02-16 12:16:48 +01005295 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005296
Michal Vaskoff006c12016-02-17 11:15:19 +01005297 /* remove parsed data */
5298 LY_TREE_FOR_SAFE(module->data, next, elem) {
5299 if (elem->module == (struct lys_module *)submodule) {
5300 lys_node_free(elem, NULL, 0);
5301 }
5302 }
5303
5304 /* remove applied deviations */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005305 for (i = 0; i < submodule->deviation_size; ++i) {
Michal Vaskoff006c12016-02-17 11:15:19 +01005306 if (submodule->deviation[i].orig_node) {
5307 resolve_augment_schema_nodeid(submodule->deviation[i].target_name, NULL, module, (const struct lys_node **)&elem);
5308 lys_node_switch(elem, submodule->deviation[i].orig_node);
Michal Vasko9f258e42016-02-11 11:36:27 +01005309 }
5310 }
5311
5312 /* remove applied augments */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005313 for (i = 0; i < submodule->augment_size; ++i) {
5314 if (submodule->augment[i].target) {
5315 LY_TREE_FOR_SAFE(submodule->augment[i].target->child, next, elem) {
5316 if (elem->parent == (struct lys_node *)&submodule->augment[i]) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005317 lys_node_free(elem, NULL, 0);
Michal Vasko9f258e42016-02-11 11:36:27 +01005318 }
5319 }
5320 }
5321 }
5322
Michal Vasko5a721fd2016-02-16 12:16:48 +01005323 lys_submodule_free(submodule, NULL);
5324
5325 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005326}
5327
Michal Vasko0d343d12015-08-24 14:57:36 +02005328/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005329struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005330yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005331{
Michal Vasko9f258e42016-02-11 11:36:27 +01005332 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005334 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005335 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005336 const char *value;
5337 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005338
Radek Krejcic071c542016-01-27 14:57:51 +01005339 unres = calloc(1, sizeof *unres);
5340 if (!unres) {
5341 LOGMEM;
5342 return NULL;
5343 }
5344
Radek Krejci722b0072016-02-01 17:09:45 +01005345 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005347 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005348 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 /* check root element */
5351 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe5e06292016-02-26 09:56:41 +01005352 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005353 goto error;
5354 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005356 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005357 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005358 goto error;
5359 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005361 module = calloc(1, sizeof *module);
5362 if (!module) {
5363 LOGMEM;
5364 goto error;
5365 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005367 module->ctx = ctx;
5368 module->name = lydict_insert(ctx, value, strlen(value));
5369 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005370 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005371
Michal Vasko9f258e42016-02-11 11:36:27 +01005372 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005373 if (read_sub_module(module, NULL, yin, unres)) {
5374 goto error;
5375 }
5376
5377 /* resolve rest of unres items */
5378 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005379 goto error;
5380 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005381
Radek Krejciff4874d2016-03-07 12:30:50 +01005382 if (revision) {
5383 /* check revision of the parsed model */
5384 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
5385 lys_free(module, NULL, 0);
5386 goto error;
5387 }
5388 }
5389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005390 /* add to the context's list of modules */
5391 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005392 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005393 if (!newlist) {
5394 LOGMEM;
5395 goto error;
5396 }
5397 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5398 newlist[i] = NULL;
5399 }
5400 ctx->models.size *= 2;
5401 ctx->models.list = newlist;
5402 }
5403 for (i = 0; ctx->models.list[i]; i++) {
5404 /* check name (name/revision) and namespace uniqueness */
5405 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005406 if (ctx->models.list[i]->rev_size == module->rev_size) {
5407 /* both have the same number of revisions */
5408 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5409 /* both have the same revision -> we already have the same module */
5410 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005411 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005412
Michal Vasko9f258e42016-02-11 11:36:27 +01005413 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005414 module = ctx->models.list[i];
5415 if (implement && !module->implemented) {
5416 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005417 }
Radek Krejcic071c542016-01-27 14:57:51 +01005418
5419 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005420 }
5421 }
Radek Krejcif647e612015-07-30 11:36:07 +02005422 /* else (both elses) keep searching, for now the caller is just adding
5423 * another revision of an already present schema
5424 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005426 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 ctx->models.list[i]->name, module->name, module->ns);
5428 goto error;
5429 }
5430 }
5431 ctx->models.list[i] = module;
5432 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005433 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005434
Radek Krejcic071c542016-01-27 14:57:51 +01005435success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005437 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005438 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005439
Michal Vasko9f258e42016-02-11 11:36:27 +01005440 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005442 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005443
5444error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005445 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005446 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005447 unres_schema_free(module, &unres);
5448
5449 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005450 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005451 return NULL;
5452 }
5453
5454 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005455
Michal Vaskoff006c12016-02-17 11:15:19 +01005456 /* remove applied deviations */
Michal Vasko9f258e42016-02-11 11:36:27 +01005457 for (i = 0; i < module->deviation_size; ++i) {
Michal Vaskoff006c12016-02-17 11:15:19 +01005458 if (module->deviation[i].orig_node) {
5459 resolve_augment_schema_nodeid(module->deviation[i].target_name, NULL, module, (const struct lys_node **)&elem);
5460 lys_node_switch(elem, module->deviation[i].orig_node);
Michal Vasko9f258e42016-02-11 11:36:27 +01005461 }
5462 }
5463
5464 /* remove applied augments */
5465 for (i = 0; i < module->augment_size; ++i) {
5466 if (module->augment[i].target) {
5467 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5468 if (elem->parent == (struct lys_node *)&module->augment[i]) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005469 lys_node_free(elem, NULL, 0);
Michal Vasko9f258e42016-02-11 11:36:27 +01005470 }
5471 }
5472 }
5473 }
5474
5475 lys_free(module, NULL, 1);
5476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005477 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005478}