blob: 6bc84df3c056efb12330915906c93c9f22f09cf7 [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>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Radek Krejcic6556022016-01-27 15:16:45 +010042/* parser.c */
43int dup_prefix_check(const char *prefix, struct lys_module *module);
44
Radek Krejcib388c152015-06-04 17:03:03 +020045#define OPT_IDENT 0x01
46#define OPT_CONFIG 0x02
47#define OPT_MODULE 0x04
48#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020049#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020050static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020051
Radek Krejcib8048692015-08-05 13:36:34 +020052static 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 +020053 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020054static 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 +020055 int resolve, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020056static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
57 LYS_NODE type, int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static 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 +020059 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static 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 +020061 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static 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 +020063 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020064static 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 +020065 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020066static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci3440cc52016-06-23 17:03:59 +020067 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020068static 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 +020069 int resolve, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020070static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
71 int resolve, struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020072static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
73 int resolve, struct unres_schema *unres);
Michal Vaskof02e3742015-08-05 16:27:02 +020074static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020075
Michal Vasko0d343d12015-08-24 14:57:36 +020076/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020077static const char *
78read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020079{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020080 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020082 /* there should be <text> child */
83 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010084 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010085 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010086 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020087 } else if (node->child->content) {
88 len = strlen(node->child->content);
89 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010090 } else {
91 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020092 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020093}
94
Michal Vasko0d343d12015-08-24 14:57:36 +020095/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020096static int
Radek Krejci9ff0a922016-07-14 13:08:05 +020097fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_iffeature *iffeat, struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +010098{
99 int r;
100 const char *value;
101
102 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200103
104 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
105 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200106error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100107 return EXIT_FAILURE;
108 }
109
Michal Vasko97b32be2016-07-25 10:59:53 +0200110 if (!(value = transform_schema2json(parent->module, value))) {
111 return EXIT_FAILURE;
112 }
113
Radek Krejci9ff0a922016-07-14 13:08:05 +0200114 r = resolve_iffeature_compile(iffeat, value, parent, unres);
115 lydict_remove(parent->module->ctx, value);
116 if (r) {
117 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100118 }
119
Radek Krejci9ff0a922016-07-14 13:08:05 +0200120 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100121}
122
123/* logs directly */
124static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200125fill_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 +0200126{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200127 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200128 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200129 int rc;
130 int c_ftrs = 0, c_base = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200131
Michal Vasko4cfcd252015-08-03 14:31:10 +0200132 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100133 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200134
Radek Krejci76512572015-08-04 09:47:08 +0200135 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200136 return EXIT_FAILURE;
137 }
Radek Krejci04581c62015-05-22 21:24:00 +0200138
Pavol Vicand6cda452016-07-13 15:08:29 +0200139 if (dup_identities_check(ident->name, module)) {
140 return EXIT_FAILURE;
141 }
142
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200143 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200144 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
145 /* garbage */
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200146 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200147 continue;
148 }
149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200150 if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200151 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100152 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200153 return EXIT_FAILURE;
154 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200155 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100156
Radek Krejci018f1f52016-08-03 16:01:20 +0200157 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
158 c_ftrs++;
159
160 } else {
161 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
162 return EXIT_FAILURE;
163 }
164 }
165
166 if (c_base) {
167 ident->base_size = 0;
168 ident->base = calloc(c_base, sizeof *ident->base);
169 if (!ident->base) {
170 LOGMEM;
171 return EXIT_FAILURE;
172 }
173 }
174
175 if (c_ftrs) {
176 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
177 if (!ident->iffeature) {
178 LOGMEM;
179 return EXIT_FAILURE;
180 }
181 }
182
183 LY_TREE_FOR(yin->child, node) {
184 if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200185 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100186 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100187 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200188 return EXIT_FAILURE;
189 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100190
Radek Krejci48464ed2016-03-17 15:44:09 +0100191 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100192 lydict_remove(module->ctx, value);
193 return EXIT_FAILURE;
194 }
195 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200196 } else if (!strcmp(node->name, "if-feature")) {
197 rc = fill_yin_iffeature((struct lys_node *)ident, node, &ident->iffeature[ident->iffeature_size], unres);
198 ident->iffeature_size++;
199 if (rc) {
200 return EXIT_FAILURE;
201 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200202 }
203 }
204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200205 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200206
207error:
208 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200209}
210
Michal Vasko0d343d12015-08-24 14:57:36 +0200211/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200212static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200213read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200214{
Radek Krejci73adb602015-07-02 18:07:40 +0200215 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200216 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200217
Radek Krejci73adb602015-07-02 18:07:40 +0200218 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200219 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
220 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200221 continue;
222 }
223
Radek Krejci41726f92015-06-19 13:11:05 +0200224 if (!strcmp(child->name, "description")) {
225 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100226 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200227 return EXIT_FAILURE;
228 }
229 restr->dsc = read_yin_subnode(ctx, child, "text");
230 if (!restr->dsc) {
231 return EXIT_FAILURE;
232 }
233 } else if (!strcmp(child->name, "reference")) {
234 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100235 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200236 return EXIT_FAILURE;
237 }
238 restr->ref = read_yin_subnode(ctx, child, "text");
239 if (!restr->ref) {
240 return EXIT_FAILURE;
241 }
242 } else if (!strcmp(child->name, "error-app-tag")) {
243 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100244 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200245 return EXIT_FAILURE;
246 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200247 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200248 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200249 } else if (!strcmp(child->name, "error-message")) {
250 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100251 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200252 return EXIT_FAILURE;
253 }
254 restr->emsg = read_yin_subnode(ctx, child, "value");
255 if (!restr->emsg) {
256 return EXIT_FAILURE;
257 }
258 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100259 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200260 return EXIT_FAILURE;
261 }
Radek Krejci41726f92015-06-19 13:11:05 +0200262 }
263
264 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200265
266error:
267 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200268}
269
Michal Vasko88c29542015-11-27 14:57:53 +0100270/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
271int
Radek Krejcib8048692015-08-05 13:36:34 +0200272fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci3a5501d2016-07-18 22:03:34 +0200273 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200274{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200275 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200276 struct lys_node *siter;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200277 struct lyxml_elem *next, *next2, *node, *child;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200278 struct lys_restr **restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200279 struct lys_type_bit bit, *bits_sc = NULL;
280 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200281 struct lys_type *dertype;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200282 int i, j, rc, val_set, c_ftrs;
Radek Krejcidc008d72016-02-17 13:12:14 +0100283 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200284 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200285 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200286 size_t len;
287 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200288
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200289 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100290 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200291 if (!value) {
292 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200293 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200294
295 i = parse_identifier(value);
296 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100297 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100298 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200299 goto error;
300 }
301 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100302 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200303 if (value[i]) {
304 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100305 name += i;
306 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100307 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100308 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200309 goto error;
310 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200311 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100312 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200313 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200314
Radek Krejci225376f2016-02-16 17:36:22 +0100315 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200316 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100317 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200318 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200319 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100320
321 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200322 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200323 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200324 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100325 ret = EXIT_FAILURE;
326 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200328 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200329
330 if (type->base == LY_TYPE_INGRP) {
331 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
332 * unresolved item left inside the grouping */
333 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
334 if (siter) {
335 if (!((struct lys_node_grp *)siter)->nacm) {
336 LOGINT;
337 goto error;
338 }
339 ((struct lys_node_grp *)siter)->nacm--;
340 } else {
341 LOGINT;
342 goto error;
343 }
344 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200345 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200346
Radek Krejcicf509982015-12-15 09:22:44 +0100347 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100348 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100349 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100350 return -1;
351 }
352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200354 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200355 /* RFC 6020 9.7.4 - bit */
356
357 /* get bit specifications, at least one must be present */
358 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200359 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
360 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100361 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200362 continue;
363 }
364
Radek Krejci994b6f62015-06-18 16:47:27 +0200365 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200366 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200367 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100368 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200369 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200370 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200371 }
372 }
Radek Krejcie663e012016-08-01 17:12:34 +0200373 dertype = &type->der->type;
374 if (!dertype->der) {
375 if (!type->info.bits.count) {
376 /* type is derived directly from buit-in bits type and bit statement is required */
377 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
378 goto error;
379 }
380 } else {
381 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
382 if (module->version < 2 && type->info.bits.count) {
383 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
384 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
385 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200386 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200387 goto error;
388 }
Radek Krejciac781922015-07-09 15:35:14 +0200389 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200390
391 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100392 if (!type->info.bits.bit) {
393 LOGMEM;
394 goto error;
395 }
Radek Krejci73adb602015-07-02 18:07:40 +0200396 p = 0;
397 i = -1;
398 LY_TREE_FOR(yin->child, next) {
399 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200400 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200401
402 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100403 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100404 goto error;
405 }
406
Radek Krejci994b6f62015-06-18 16:47:27 +0200407 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200408 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200409 type->info.bits.count = i + 1;
410 goto error;
411 }
412
Radek Krejcie663e012016-08-01 17:12:34 +0200413 if (!dertype->der) { /* directly derived type from bits built-in type */
414 /* check the name uniqueness */
415 for (j = 0; j < i; j++) {
416 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
417 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
418 type->info.bits.count = i + 1;
419 goto error;
420 }
421 }
422 } else {
423 /* restricted bits type - the name MUST be used in the base type */
424 bits_sc = dertype->info.bits.bit;
425 for (j = 0; j < dertype->info.bits.count; j++) {
426 if (ly_strequal(bits_sc[j].name, value, 1)) {
427 break;
428 }
429 }
430 if (j == dertype->info.bits.count) {
431 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200432 type->info.bits.count = i + 1;
433 goto error;
434 }
435 }
436
Radek Krejcie663e012016-08-01 17:12:34 +0200437
Radek Krejci0d70c372015-07-02 16:23:10 +0200438 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200439 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200440 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
441 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200442 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200443 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200444
Radek Krejci0d70c372015-07-02 16:23:10 +0200445 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200446 if (p_ != -1) {
447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
448 type->info.bits.count = i + 1;
449 goto error;
450 }
451
Radek Krejci0d70c372015-07-02 16:23:10 +0200452 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200453 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200454
455 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200456 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100457 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200458 type->info.bits.count = i + 1;
459 goto error;
460 }
461 type->info.bits.bit[i].pos = (uint32_t)p_;
462
Radek Krejcie663e012016-08-01 17:12:34 +0200463 if (!dertype->der) { /* directly derived type from bits built-in type */
464 /* keep the highest enum value for automatic increment */
465 if (type->info.bits.bit[i].pos >= p) {
466 p = type->info.bits.bit[i].pos;
467 p++;
468 } else {
469 /* check that the value is unique */
470 for (j = 0; j < i; j++) {
471 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
472 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
473 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
474 type->info.bits.bit[j].name);
475 type->info.bits.count = i + 1;
476 goto error;
477 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200478 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200479 }
480 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200481
482 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
483 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200484 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100485 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200486 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200487 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200488 }
Radek Krejcie663e012016-08-01 17:12:34 +0200489
490 if (!dertype->der) { /* directly derived type from bits built-in type */
491 if (p_ == -1) {
492 /* assign value automatically */
493 if (p > UINT32_MAX) {
494 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
495 type->info.bits.count = i + 1;
496 goto error;
497 }
498 type->info.bits.bit[i].pos = (uint32_t)p;
499 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
500 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200501 }
Radek Krejcie663e012016-08-01 17:12:34 +0200502 } else { /* restricted bits type */
503 if (p_ == -1) {
504 /* automatically assign position from base type */
505 type->info.bits.bit[i].pos = bits_sc[j].pos;
506 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
507 } else {
508 /* check that the assigned position corresponds to the original
509 * position of the bit in the base type */
510 if (p_ != bits_sc[j].pos) {
511 /* p_ - assigned position in restricted bits
512 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
513 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200514 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200515 type->info.bits.count = i + 1;
516 goto error;
517 }
518 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200519 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200520
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200521 /* if-features */
522 if (c_ftrs) {
523 bits_sc = &type->info.bits.bit[i];
524 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
525 if (!bits_sc->iffeature) {
526 LOGMEM;
527 type->info.bits.count = i + 1;
528 goto error;
529 }
530
531 LY_TREE_FOR(next->child, node) {
532 if (!strcmp(node->name, "if-feature")) {
533 rc = fill_yin_iffeature((struct lys_node *)type->parent, node,
534 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
535 bits_sc->iffeature_size++;
536 if (rc) {
537 type->info.bits.count = i + 1;
538 goto error;
539 }
540 }
541 }
542 }
543
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200544 /* keep them ordered by position */
545 j = i;
546 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
547 /* switch them */
548 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
549 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
550 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
551 j--;
552 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200553 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200554 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200556 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200557 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200558 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200559 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
560 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200561 continue;
562 }
563
Radek Krejcif9401c32015-06-26 16:47:36 +0200564 if (!strcmp(node->name, "range")) {
565 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100566 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200567 goto error;
568 }
569
570 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200571 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100572 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200573 goto error;
574 }
575 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100576 if (!type->info.dec64.range) {
577 LOGMEM;
578 goto error;
579 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200580 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
581
582 /* get possible substatements */
583 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
584 goto error;
585 }
586 } else if (!strcmp(node->name, "fraction-digits")) {
587 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100588 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200589 goto error;
590 }
591 GETVAL(value, node, "value");
592 v = strtol(value, NULL, 10);
593
594 /* range check */
595 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100596 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200597 goto error;
598 }
599 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200600 type->info.dec64.div = 10;
601 for (i = 1; i < v; i++) {
602 type->info.dec64.div *= 10;
603 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200604 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100605 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200606 goto error;
607 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200608 }
609
610 /* mandatory sub-statement(s) check */
611 if (!type->info.dec64.dig && !type->der->type.der) {
612 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100613 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200614 goto error;
615 }
Radek Krejci7511f402015-07-10 09:56:30 +0200616 if (type->info.dec64.dig && type->der->type.der) {
617 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100618 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200619 goto error;
620 }
Radek Krejcib51d5932016-09-08 14:02:52 +0200621
622 /* copy fraction-digits specification from parent type for easier internal use */
623 if (type->der->type.der) {
624 type->info.dec64.dig = type->der->type.info.dec64.dig;
625 type->info.dec64.div = type->der->type.info.dec64.div;
626 }
627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200630 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200631 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200632
Radek Krejci994b6f62015-06-18 16:47:27 +0200633 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200634 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200635 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
636 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100637 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200638 continue;
639 }
640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200643 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100644 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200645 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200646 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200647 }
648 }
Radek Krejcie663e012016-08-01 17:12:34 +0200649 dertype = &type->der->type;
650 if (!dertype->der) {
651 if (!type->info.enums.count) {
652 /* type is derived directly from buit-in enumeartion type and enum statement is required */
653 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
654 goto error;
655 }
656 } else {
657 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
658 if (module->version < 2 && type->info.enums.count) {
659 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
660 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
661 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200662 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200663 goto error;
664 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200665 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200666
Radek Krejci1574a8d2015-08-03 14:16:52 +0200667 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100668 if (!type->info.enums.enm) {
669 LOGMEM;
670 goto error;
671 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200672
Radek Krejcie663e012016-08-01 17:12:34 +0200673 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200674 i = -1;
675 LY_TREE_FOR(yin->child, next) {
676 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200677 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200678
679 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100680 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100681 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
682 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100683 goto error;
684 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200685 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200686 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200687 type->info.enums.count = i + 1;
688 goto error;
689 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200692 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200693 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100694 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200695 type->info.enums.count = i + 1;
696 goto error;
697 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200698
Radek Krejcie663e012016-08-01 17:12:34 +0200699 if (!dertype->der) { /* directly derived type from enumeration built-in type */
700 /* check the name uniqueness */
701 for (j = 0; j < i; j++) {
702 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
703 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
704 type->info.enums.count = i + 1;
705 goto error;
706 }
707 }
708 } else {
709 /* restricted enumeration type - the name MUST be used in the base type */
710 enms_sc = dertype->info.enums.enm;
711 for (j = 0; j < dertype->info.enums.count; j++) {
712 if (ly_strequal(enms_sc[j].name, value, 1)) {
713 break;
714 }
715 }
716 if (j == dertype->info.enums.count) {
717 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200718 type->info.enums.count = i + 1;
719 goto error;
720 }
721 }
Radek Krejci04581c62015-05-22 21:24:00 +0200722
Radek Krejcie663e012016-08-01 17:12:34 +0200723 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200724 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200725 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
726 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200727 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200728 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729
Radek Krejci0d70c372015-07-02 16:23:10 +0200730 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200731 if (val_set) {
732 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
733 type->info.enums.count = i + 1;
734 goto error;
735 }
736
Radek Krejci0d70c372015-07-02 16:23:10 +0200737 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200738 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200739
740 /* range check */
741 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100742 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200743 type->info.enums.count = i + 1;
744 goto error;
745 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200746 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200747
Radek Krejcie663e012016-08-01 17:12:34 +0200748 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200749 if (!i) {
750 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200751 v = type->info.enums.enm[i].value;
752 v++;
753 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200754 /* keep the highest enum value for automatic increment */
755 if (type->info.enums.enm[i].value >= v) {
756 v = type->info.enums.enm[i].value;
757 v++;
758 } else {
759 /* check that the value is unique */
760 for (j = 0; j < i; j++) {
761 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
762 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
763 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
764 type->info.enums.enm[j].name);
765 type->info.enums.count = i + 1;
766 goto error;
767 }
Radek Krejcie663e012016-08-01 17:12:34 +0200768 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200769 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200770 }
771 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200772 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200773
774 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
775 c_ftrs++;
776
Radek Krejci0d70c372015-07-02 16:23:10 +0200777 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100778 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200779 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200780 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200781 }
Radek Krejcie663e012016-08-01 17:12:34 +0200782
783 if (!dertype->der) { /* directly derived type from enumeration */
784 if (!val_set) {
785 /* assign value automatically */
786 if (v > INT32_MAX) {
787 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
788 type->info.enums.count = i + 1;
789 goto error;
790 }
791 type->info.enums.enm[i].value = v;
792 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
793 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200794 }
Radek Krejcie663e012016-08-01 17:12:34 +0200795 } else { /* restricted enum type */
796 if (!val_set) {
797 /* automatically assign value from base type */
798 type->info.enums.enm[i].value = enms_sc[j].value;
799 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
800 } else {
801 /* check that the assigned value corresponds to the original
802 * value of the enum in the base type */
803 if (v_ != enms_sc[j].value) {
804 /* v_ - assigned value in restricted enum
805 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
806 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +0200807 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +0200808 type->info.enums.count = i + 1;
809 goto error;
810 }
811 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200812 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200813
814 /* if-features */
815 if (c_ftrs) {
816 enms_sc = &type->info.enums.enm[i];
817 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
818 if (!enms_sc->iffeature) {
819 LOGMEM;
820 type->info.enums.count = i + 1;
821 goto error;
822 }
823
824 LY_TREE_FOR(next->child, node) {
825 if (!strcmp(node->name, "if-feature")) {
826 rc = fill_yin_iffeature((struct lys_node *)type->parent, node,
827 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
828 enms_sc->iffeature_size++;
829 if (rc) {
830 type->info.enums.count = i + 1;
831 goto error;
832 }
833 }
834 }
835 }
836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200837 }
838 break;
839
840 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200841 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200842
Michal Vaskof2d43962016-09-02 11:10:16 +0200843 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200844 LY_TREE_FOR_SAFE(yin->child, next, node) {
845 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
846 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100847 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200848 continue;
849 }
850
Michal Vaskoe29c6622015-11-27 15:02:31 +0100851 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100852 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200853 goto error;
854 }
Michal Vaskof2d43962016-09-02 11:10:16 +0200855
856 GETVAL(value, yin->child, "name");
857 /* store in the JSON format */
858 value = transform_schema2json(module, value);
859 if (!value) {
860 goto error;
861 }
862 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
863 lydict_remove(module->ctx, value);
864
865 if (rc == -1) {
866 goto error;
867 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200868 }
869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200870 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200871 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +0200872 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +0200873 break;
874 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100875 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200876 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +0200877 } else {
878 if (type->der->type.der) {
879 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
880 goto error;
881 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200882 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100884 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200885 goto error;
886 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887 break;
888
889 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200890 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200891 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200892 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
893 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200894 continue;
895 }
896
Radek Krejciaf351422015-06-19 14:49:38 +0200897 if (!strcmp(node->name, "require-instance")) {
898 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100899 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200900 goto error;
901 }
902 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200903 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200904 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200905 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200906 type->info.inst.req = -1;
907 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100908 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200909 goto error;
910 }
911 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100912 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200913 goto error;
914 }
Radek Krejciaf351422015-06-19 14:49:38 +0200915 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 break;
918
Radek Krejcif2860132015-06-20 12:37:20 +0200919 case LY_TYPE_BINARY:
920 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 case LY_TYPE_INT8:
922 case LY_TYPE_INT16:
923 case LY_TYPE_INT32:
924 case LY_TYPE_INT64:
925 case LY_TYPE_UINT8:
926 case LY_TYPE_UINT16:
927 case LY_TYPE_UINT32:
928 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200929 /* RFC 6020 9.2.4 - range */
930
931 /* length and range are actually the same restriction, so process
932 * them by this common code, we just need to differ the name and
933 * structure where the information will be stored
934 */
935 if (type->base == LY_TYPE_BINARY) {
936 restr = &type->info.binary.length;
937 name = "length";
938 } else {
939 restr = &type->info.num.range;
940 name = "range";
941 }
942
Radek Krejci73adb602015-07-02 18:07:40 +0200943 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200944 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
945 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200946 continue;
947 }
948
Radek Krejcif2860132015-06-20 12:37:20 +0200949 if (!strcmp(node->name, name)) {
950 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100951 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200952 goto error;
953 }
954
955 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200956 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100957 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200958 goto error;
959 }
960 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100961 if (!(*restr)) {
962 LOGMEM;
963 goto error;
964 }
Radek Krejcif2860132015-06-20 12:37:20 +0200965 (*restr)->expr = lydict_insert(module->ctx, value, 0);
966
967 /* get possible substatements */
968 if (read_restr_substmt(module->ctx, *restr, node)) {
969 goto error;
970 }
971 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100972 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200973 goto error;
974 }
Radek Krejcif2860132015-06-20 12:37:20 +0200975 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200976 break;
977
978 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200979 /* flag resolving for later use */
980 if (!tpdftype) {
981 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
982 if (siter) {
983 /* just a flag - do not resolve */
984 tpdftype = 1;
985 }
986 }
987
Radek Krejcidc4c1412015-06-19 15:39:54 +0200988 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200989 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200990 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
991 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200992 continue;
993 }
994
Michal Vasko88c29542015-11-27 14:57:53 +0100995 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200996 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100997 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200998 goto error;
999 }
1000
1001 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001002 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001003 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001004 if (!type->info.lref.path) {
1005 goto error;
1006 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001007
1008 /* try to resolve leafref path only when this is instantiated
1009 * leaf, so it is not:
1010 * - typedef's type,
1011 * - in grouping definition,
1012 * - just instantiated in a grouping definition,
1013 * because in those cases the nodes referenced in path might not be present
1014 * and it is not a bug. */
1015 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001016 goto error;
1017 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001018 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001019 if (type->info.lref.req) {
1020 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1021 goto error;
1022 }
1023 GETVAL(value, node, "value");
1024 if (!strcmp(value, "true")) {
1025 type->info.lref.req = 1;
1026 } else if (!strcmp(value, "false")) {
1027 type->info.lref.req = -1;
1028 } else {
1029 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1030 goto error;
1031 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001032 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001033 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001034 goto error;
1035 }
Radek Krejci73adb602015-07-02 18:07:40 +02001036 }
1037
Radek Krejci742be352016-07-17 12:18:54 +02001038 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001039 if (!type->der->type.der) {
1040 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Michal Vasko01c6fd22016-05-20 11:43:05 +02001041 goto error;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001042 } else {
1043 /* copy leafref definition into the derived type */
1044 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1045 /* and resolve the path at the place we are (if not in grouping/typedef) */
1046 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1047 goto error;
1048 }
1049
1050 /* add pointer to leafref target, only on leaves (not in typedefs) */
1051 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1052 goto error;
1053 }
Michal Vasko01c6fd22016-05-20 11:43:05 +02001054 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001055 }
Radek Krejci742be352016-07-17 12:18:54 +02001056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001057 break;
1058
1059 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001060 /* RFC 6020 9.4.4 - length */
1061 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001062 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001063 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001064 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1065 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001066 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001067 continue;
1068 }
1069
Radek Krejci3733a802015-06-19 13:43:21 +02001070 if (!strcmp(node->name, "length")) {
1071 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001072 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001073 goto error;
1074 }
1075
1076 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001077 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001078 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001079 goto error;
1080 }
1081 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001082 if (!type->info.str.length) {
1083 LOGMEM;
1084 goto error;
1085 }
Radek Krejci3733a802015-06-19 13:43:21 +02001086 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1087
Radek Krejci5fbc9162015-06-19 14:11:11 +02001088 /* get possible sub-statements */
1089 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001090 goto error;
1091 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001092 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001093 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001094 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001095 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001096 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001097 goto error;
1098 }
1099 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001100 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001101 if (i) {
1102 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001103 if (!type->info.str.patterns) {
1104 LOGMEM;
1105 goto error;
1106 }
Radek Krejci73adb602015-07-02 18:07:40 +02001107 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001108 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001109 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001110 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001111 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001112 goto error;
1113 }
Michal Vasko69068852015-07-13 14:34:31 +02001114
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001115 modifier = 0x06; /* ACK */
1116 name = NULL;
1117 LY_TREE_FOR_SAFE(node->child, next2, child) {
1118 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1119 /* garbage */
1120 lyxml_free(module->ctx, child);
1121 continue;
1122 }
1123
1124 if (module->version >= 2 && !strcmp(child->name, "modifier")) {
1125 if (name) {
1126 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1127 goto error;
1128 }
1129
1130 GETVAL(name, child, "value");
1131 if (!strcmp(name, "invert-match")) {
1132 modifier = 0x15; /* NACK */
1133 } else {
1134 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1135 goto error;
1136 }
1137 lyxml_free(module->ctx, child);
1138 }
1139 }
1140
1141 len = strlen(value);
1142 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1143 buf[0] = modifier;
1144 strcpy(&buf[1], value);
1145
1146 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001147
1148 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +01001149 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +02001150 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001151 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001152 goto error;
1153 }
Radek Krejci73adb602015-07-02 18:07:40 +02001154 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001155 }
1156 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157 break;
1158
1159 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001160 /* RFC 6020 7.4 - type */
1161 /* count number of types in union */
1162 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001163 LY_TREE_FOR_SAFE(yin->child, next, node) {
1164 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1165 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001166 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001167 continue;
1168 }
1169
Radek Krejcie4c366b2015-07-02 10:11:31 +02001170 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001171 if (type->der->type.der) {
1172 /* type can be a substatement only in "union" type, not in derived types */
1173 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1174 goto error;
1175 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001176 i++;
1177 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001178 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001179 goto error;
1180 }
1181 }
1182
Radek Krejci038d5d92016-09-12 15:07:15 +02001183 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001184 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001185 goto error;
1186 }
1187
1188 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001189 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001190 if (!type->info.uni.types) {
1191 LOGMEM;
1192 goto error;
1193 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001194 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001195 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001196 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001197 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001198 if (!rc) {
1199 type->info.uni.count++;
1200
Radek Krejci7de36cf2016-09-12 16:18:50 +02001201 if (module->version < 2) {
1202 /* union's type cannot be empty or leafref */
1203 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1204 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1205 rc = -1;
1206 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1207 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1208 rc = -1;
1209 }
Michal Vasko88c29542015-11-27 14:57:53 +01001210 }
1211 }
1212 if (rc) {
1213 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1214 for (i = 0; i < type->info.uni.count; ++i) {
1215 lys_type_free(module->ctx, &type->info.uni.types[i]);
1216 }
1217 free(type->info.uni.types);
1218 type->info.uni.types = NULL;
1219 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001220 type->der = NULL;
1221 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001222
1223 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001224 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001225 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001226 goto error;
1227 }
Michal Vasko88c29542015-11-27 14:57:53 +01001228 }
1229 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001230
Michal Vasko88c29542015-11-27 14:57:53 +01001231 case LY_TYPE_BOOL:
1232 case LY_TYPE_EMPTY:
1233 /* no sub-statement allowed */
1234 LY_TREE_FOR(yin->child, node) {
1235 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001236 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001237 goto error;
1238 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001239 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 break;
1241
1242 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001243 LOGINT;
1244 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001245 }
1246
1247 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001248
1249error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001250 if (type->module_name) {
1251 lydict_remove(module->ctx, type->module_name);
1252 type->module_name = NULL;
1253 }
1254 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001255}
1256
Michal Vasko0d343d12015-08-24 14:57:36 +02001257/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001258static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001259fill_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 +02001260{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001261 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001262 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +01001263 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001265 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001266 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001267 goto error;
1268 }
1269 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001271 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001272 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001273 goto error;
1274 }
Radek Krejcieac35532015-05-31 19:09:15 +02001275
Michal Vasko88c29542015-11-27 14:57:53 +01001276 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001277 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1278 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001279 continue;
1280 }
1281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001282 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001283 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001284 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001285 goto error;
1286 }
Michal Vasko88c29542015-11-27 14:57:53 +01001287 /* HACK for unres */
1288 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001289 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001290 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001291 goto error;
1292 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001293 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001294 } else if (!strcmp(node->name, "default")) {
1295 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001296 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001297 goto error;
1298 }
1299 GETVAL(value, node, "value");
1300 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1301 } else if (!strcmp(node->name, "units")) {
1302 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001303 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 goto error;
1305 }
1306 GETVAL(value, node, "name");
1307 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1308 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001309 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001310 goto error;
1311 }
1312 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001314 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001315 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001316 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317 goto error;
1318 }
Radek Krejcieac35532015-05-31 19:09:15 +02001319
Michal Vasko478c4652016-07-21 12:55:01 +02001320 /* check default value (if not defined, there still could be some restrictions
1321 * that need to be checked against a default value from a derived type) */
1322 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
1323 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001324 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001326 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001327
1328error:
1329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001330 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001331}
1332
Michal Vasko0d343d12015-08-24 14:57:36 +02001333/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001334static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001335fill_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 +02001336{
1337 const char *value;
1338 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001339 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001340
Radek Krejcib05774c2015-06-18 13:52:59 +02001341 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001342 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001343 goto error;
1344 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001345 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001346 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001347
Radek Krejci76512572015-08-04 09:47:08 +02001348 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001349 goto error;
1350 }
1351
1352 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001353 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1354 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001355 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001356 continue;
1357 }
1358
Radek Krejci3cf9e222015-06-18 11:37:50 +02001359 if (!strcmp(child->name, "if-feature")) {
1360 c++;
1361 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001362 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001363 goto error;
1364 }
1365 }
1366
1367 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001368 f->iffeature = calloc(c, sizeof *f->iffeature);
1369 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001370 LOGMEM;
1371 goto error;
1372 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001373 }
Radek Krejci73adb602015-07-02 18:07:40 +02001374 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001375 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1376 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001377 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001378 goto error;
1379 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001380 }
1381
Radek Krejcic79c6b12016-07-26 15:11:49 +02001382 /* check for circular dependencies */
1383 if (f->iffeature_size) {
1384 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1385 goto error;
1386 }
1387 }
1388
Radek Krejci3cf9e222015-06-18 11:37:50 +02001389 return EXIT_SUCCESS;
1390
1391error:
1392
1393 return EXIT_FAILURE;
1394}
1395
Michal Vasko0d343d12015-08-24 14:57:36 +02001396/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001397static int
Radek Krejcib8048692015-08-05 13:36:34 +02001398fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001399{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001402 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001403 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001404 if (!must->expr) {
1405 goto error;
1406 }
Radek Krejci800af702015-06-02 13:46:01 +02001407
Radek Krejci41726f92015-06-19 13:11:05 +02001408 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001409
Michal Vasko77dc5652016-02-15 12:32:42 +01001410error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001411 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001412}
1413
Radek Krejci581ce772015-11-10 17:22:40 +01001414static int
Michal Vasko88c29542015-11-27 14:57:53 +01001415fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1416 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001417{
1418 int i, j;
1419 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001420 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001421
1422 /* get unique value (list of leafs supposed to be unique */
1423 GETVAL(value, yin, "tag");
1424
1425 /* count the number of unique leafs in the value */
1426 vaux = value;
1427 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001428 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001429 while (isspace(*vaux)) {
1430 vaux++;
1431 }
1432 }
1433 unique->expr_size++;
1434 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001435 if (!unique->expr) {
1436 LOGMEM;
1437 goto error;
1438 }
Radek Krejci581ce772015-11-10 17:22:40 +01001439
1440 for (i = 0; i < unique->expr_size; i++) {
1441 vaux = strpbrk(value, " \t\n");
1442 if (!vaux) {
1443 /* the last token, lydict_insert() will count its size on its own */
1444 vaux = value;
1445 }
1446
1447 /* store token into unique structure */
1448 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1449
1450 /* check that the expression does not repeat */
1451 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001452 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001453 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1454 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001455 goto error;
1456 }
1457 }
1458
1459 /* try to resolve leaf */
1460 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001461 unique_info = malloc(sizeof *unique_info);
1462 unique_info->list = parent;
1463 unique_info->expr = unique->expr[i];
1464 unique_info->trg_type = &unique->trg_type;
1465 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001466 goto error;
1467 }
Radek Krejci581ce772015-11-10 17:22:40 +01001468 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001469 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001470 goto error;
1471 }
1472 }
1473
1474 /* move to next token */
1475 value = vaux;
1476 while(isspace(*value)) {
1477 value++;
1478 }
1479 }
1480
1481 return EXIT_SUCCESS;
1482
1483error:
1484 return EXIT_FAILURE;
1485}
1486
Michal Vasko0d343d12015-08-24 14:57:36 +02001487/* logs directly
1488 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001489 * type: 0 - min, 1 - max
1490 */
1491static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001492deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001493{
1494 const char *value;
1495 char *endptr;
1496 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001497 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001498
Michal Vaskof7e57d52016-03-07 11:31:09 +01001499 /* del min/max is forbidden */
1500 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001501 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001502 goto error;
1503 }
1504
Radek Krejcieb00f512015-07-01 16:44:58 +02001505 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001506 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001507 max = &((struct lys_node_leaflist *)target)->max;
1508 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001509 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001510 max = &((struct lys_node_list *)target)->max;
1511 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001513 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1514 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001515 goto error;
1516 }
1517
1518 GETVAL(value, node, "value");
1519 while (isspace(value[0])) {
1520 value++;
1521 }
1522
Radek Krejci0d7b2472016-02-12 11:11:03 +01001523 if (type && !strcmp(value, "unbounded")) {
1524 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001525 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001526 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001527 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001528 /* convert it to uint32_t */
1529 errno = 0;
1530 endptr = NULL;
1531 val = strtoul(value, &endptr, 10);
1532 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001533 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001534 goto error;
1535 }
1536 if (type) {
1537 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001538 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001539 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001540 } else {
1541 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001542 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001543 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001544 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001545 }
1546
1547 if (d->mod == LY_DEVIATE_ADD) {
1548 /* check that there is no current value */
1549 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001550 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1551 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001552 goto error;
1553 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001554 } else if (d->mod == LY_DEVIATE_RPL) {
1555 /* unfortunately, there is no way to check reliably that there
1556 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001557 }
1558
Michal Vaskof7e57d52016-03-07 11:31:09 +01001559 /* add (already checked) and replace */
1560 /* set new value specified in deviation */
1561 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001562
Pavol Vican09adcc32016-08-25 10:51:36 +02001563 /* check min-elements is smaller than max-elements */
1564 if (*max && *min > *max) {
1565 if (type) {
1566 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
1567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1568 } else {
1569 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
1570 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1571 }
1572 goto error;
1573 }
1574
Radek Krejcieb00f512015-07-01 16:44:58 +02001575 return EXIT_SUCCESS;
1576
1577error:
1578
1579 return EXIT_FAILURE;
1580}
1581
Michal Vasko0d343d12015-08-24 14:57:36 +02001582/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001583static int
Michal Vasko88c29542015-11-27 14:57:53 +01001584fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1585 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001586{
1587 const char *value, **stritem;
1588 struct lyxml_elem *next, *child, *develem;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001589 int c_dev = 0, c_must, c_uniq, c_dflt;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001590 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001591 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001592 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001593 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001594 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001595 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001596 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001597 struct lys_node_leaf *leaf = NULL;
1598 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001599 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001600 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001601 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001602 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001603 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001604 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001605 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02001606
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001607 ctx = module->ctx;
1608
Radek Krejcieb00f512015-07-01 16:44:58 +02001609 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001610 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001611 if (!dev->target_name) {
1612 goto error;
1613 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001614
1615 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001616 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1617 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001618 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001619 goto error;
1620 }
Radek Krejcic4283442016-04-22 09:19:27 +02001621 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001622 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1623 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001624 goto error;
1625 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001626
1627 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001628 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1629 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001630 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001631 continue;
1632 }
1633
Radek Krejcieb00f512015-07-01 16:44:58 +02001634 if (!strcmp(child->name, "description")) {
1635 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001636 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 goto error;
1638 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001639 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001640 if (!dev->dsc) {
1641 goto error;
1642 }
1643 } else if (!strcmp(child->name, "reference")) {
1644 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001645 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 goto error;
1647 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001648 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001649 if (!dev->ref) {
1650 goto error;
1651 }
1652 } else if (!strcmp(child->name, "deviate")) {
1653 c_dev++;
1654
Michal Vasko345da0a2015-12-02 10:35:55 +01001655 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001656 * further processed later
1657 */
1658 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001659
Radek Krejcieb00f512015-07-01 16:44:58 +02001660 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001661 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001662 goto error;
1663 }
1664
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001665 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 }
1667
1668 if (c_dev) {
1669 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001670 if (!dev->deviate) {
1671 LOGMEM;
1672 goto error;
1673 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001674 } else {
1675 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1676 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001677 }
1678
1679 LY_TREE_FOR(yin->child, develem) {
1680 /* init */
1681 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001682 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001683 c_must = 0;
1684 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001685 c_dflt = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001686
1687 /* get deviation type */
1688 GETVAL(value, develem, "value");
1689 if (!strcmp(value, "not-supported")) {
1690 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1691 /* no property expected in this case */
1692 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001693 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001694 goto error;
1695 }
1696
Radek Krejci5b917642015-07-02 09:03:13 +02001697 /* and neither any other deviate statement is expected,
1698 * not-supported deviation must be the only deviation of the target
1699 */
1700 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001701 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1702 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001703 goto error;
1704 }
1705
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001706 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001707 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1708 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1709 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001710 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1711 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001712 goto error;
1713 }
1714 }
1715 }
Radek Krejci5b917642015-07-02 09:03:13 +02001716
Michal Vaskoff006c12016-02-17 11:15:19 +01001717 /* unlink and store the original node */
1718 lys_node_unlink(dev_target);
1719 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001720
Radek Krejci5b917642015-07-02 09:03:13 +02001721 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02001722 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02001723 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001724 } else if (!strcmp(value, "add")) {
1725 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1726 } else if (!strcmp(value, "replace")) {
1727 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1728 } else if (!strcmp(value, "delete")) {
1729 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1730 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001731 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001732 goto error;
1733 }
1734 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001735 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001736
Michal Vaskoff006c12016-02-17 11:15:19 +01001737 /* store a shallow copy of the original node */
1738 if (!dev->orig_node) {
1739 memset(&tmp_unres, 0, sizeof tmp_unres);
1740 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1741 /* just to be safe */
1742 if (tmp_unres.count) {
1743 LOGINT;
1744 goto error;
1745 }
1746 }
1747
Radek Krejcieb00f512015-07-01 16:44:58 +02001748 /* process deviation properties */
1749 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001750 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1751 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001752 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001753 continue;
1754 }
1755
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001757 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001758 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001759 goto error;
1760 }
1761
1762 /* for we deviate from RFC 6020 and allow config property even it is/is not
1763 * specified in the target explicitly since config property inherits. So we expect
1764 * that config is specified in every node. But for delete, we check that the value
1765 * is the same as here in deviation
1766 */
1767 GETVAL(value, child, "value");
1768 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001769 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001770 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001771 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001772 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001773 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001774 goto error;
1775 }
1776
1777 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001778 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001779 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001780 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001781 } else { /* add and replace are the same in this case */
1782 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001783 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001784
1785 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001786 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001787 }
1788 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001789 c_dflt++;
1790
1791 /* check target node type */
1792 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1793 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1794 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1795 goto error;
1796 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1797 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1798 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1799 goto error;
1800 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
1801 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1802 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001803 goto error;
1804 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001805
Radek Krejcid5a5c282016-08-15 15:38:08 +02001806 /* skip lyxml_free() at the end of the loop, this node will be processed later */
1807 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02001808
Radek Krejcieb00f512015-07-01 16:44:58 +02001809 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001810 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001811 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001812 goto error;
1813 }
1814
1815 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001816 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001817 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1818 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001819 goto error;
1820 }
1821
1822 GETVAL(value, child, "value");
1823 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001824 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001826 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001827 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001828 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001829 goto error;
1830 }
1831
1832 if (d->mod == LY_DEVIATE_ADD) {
1833 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001834 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001835 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1836 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001837 goto error;
1838 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001839
Radek Krejci841ec082016-04-05 13:05:17 +02001840 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02001841 if (d->flags & LYS_MAND_TRUE) {
1842 if (dev_target->nodetype == LYS_CHOICE) {
1843 if (((struct lys_node_choice *)(dev_target))->dflt) {
1844 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1845 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1846 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
1847 goto error;
1848 }
1849 } else if (dev_target->nodetype == LYS_LEAF) {
1850 if (((struct lys_node_leaf *)(dev_target))->dflt) {
1851 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1852 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1853 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
1854 goto error;
1855 }
1856 }
Radek Krejci841ec082016-04-05 13:05:17 +02001857 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001858
Michal Vasko21be1b32016-03-07 12:31:34 +01001859 dev_target->flags |= d->flags & LYS_MAND_MASK;
1860 } else if (d->mod == LY_DEVIATE_RPL) {
1861 /* check that there was a value before */
1862 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001863 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1864 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001865 goto error;
1866 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001867
Michal Vasko21be1b32016-03-07 12:31:34 +01001868 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001869 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001870 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001871 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001872 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001873 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001874 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001875
1876 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
1877 for (parent = dev_target->parent;
1878 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1879 parent = parent->parent) {
1880 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1881 /* stop also on presence containers */
1882 break;
1883 }
1884 }
1885 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1886 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1887 if (lyp_check_mandatory_choice(parent)) {
1888 goto error;
1889 }
1890 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001891 } else if (!strcmp(child->name, "min-elements")) {
1892 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001893 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001894 goto error;
1895 }
1896 f_min = 1;
1897
Michal Vasko60f4b452016-02-12 11:02:55 +01001898 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001899 goto error;
1900 }
1901 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001902 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001903 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001904 goto error;
1905 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001906 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001907
Michal Vasko60f4b452016-02-12 11:02:55 +01001908 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001909 goto error;
1910 }
1911 } else if (!strcmp(child->name, "must")) {
1912 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001913 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001914 continue;
1915 } else if (!strcmp(child->name, "type")) {
1916 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001917 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001918 goto error;
1919 }
1920
Michal Vaskof7e57d52016-03-07 11:31:09 +01001921 /* add, del type is forbidden */
1922 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001923 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001924 goto error;
1925 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001926 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001927 goto error;
1928 }
1929
Radek Krejcieb00f512015-07-01 16:44:58 +02001930 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001931 if (dev_target->nodetype == LYS_LEAF) {
1932 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001933 if (((struct lys_node_leaf *)dev_target)->dflt) {
1934 ly_set_add(dflt_check, dev_target, 0);
1935 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001936 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1937 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001938 if (((struct lys_node_leaflist *)dev_target)->dflt) {
1939 ly_set_add(dflt_check, dev_target, 0);
1940 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001941 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001942 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1943 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001944 goto error;
1945 }
1946
Radek Krejcieb00f512015-07-01 16:44:58 +02001947 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001948 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001949 /* HACK for unres */
1950 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001951 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001952 goto error;
1953 }
1954 d->type = t;
1955 } else if (!strcmp(child->name, "unique")) {
1956 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001957 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001958 continue;
1959 } else if (!strcmp(child->name, "units")) {
1960 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001961 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001962 goto error;
1963 }
1964
1965 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001966 if (dev_target->nodetype == LYS_LEAFLIST) {
1967 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1968 } else if (dev_target->nodetype == LYS_LEAF) {
1969 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001970 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001971 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1972 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001973 goto error;
1974 }
1975
1976 /* get units value */
1977 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001978 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001979
1980 /* apply to target */
1981 if (d->mod == LY_DEVIATE_ADD) {
1982 /* check that there is no current value */
1983 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001984 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1985 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001986 goto error;
1987 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001988
Michal Vasko21be1b32016-03-07 12:31:34 +01001989 *stritem = lydict_insert(ctx, value, 0);
1990 } else if (d->mod == LY_DEVIATE_RPL) {
1991 /* check that there was a value before */
1992 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001993 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1994 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001995 goto error;
1996 }
1997
1998 lydict_remove(ctx, *stritem);
1999 *stritem = lydict_insert(ctx, value, 0);
2000 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002001 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002002 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002003 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2004 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002005 goto error;
2006 }
2007 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002008 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002009 }
2010 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002011 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002012 goto error;
2013 }
2014
Michal Vasko88c29542015-11-27 14:57:53 +01002015 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002016 }
2017
2018 if (c_must) {
2019 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002020 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002021 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002022 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2023 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002024 break;
Radek Krejci76512572015-08-04 09:47:08 +02002025 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002026 trg_must = &((struct lys_node_container *)dev_target)->must;
2027 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002028 break;
Radek Krejci76512572015-08-04 09:47:08 +02002029 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002030 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2031 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002032 break;
Radek Krejci76512572015-08-04 09:47:08 +02002033 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002034 trg_must = &((struct lys_node_list *)dev_target)->must;
2035 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002036 break;
Radek Krejci76512572015-08-04 09:47:08 +02002037 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002038 case LYS_ANYDATA:
2039 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2040 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002041 break;
2042 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002043 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2044 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002045 goto error;
2046 }
2047
Michal Vasko508a50d2016-09-07 14:50:33 +02002048 dev_target->flags &= ~LYS_XPATH_DEP;
2049
Radek Krejcieb00f512015-07-01 16:44:58 +02002050 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002051 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002052 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002053 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002054 } else if (d->mod == LY_DEVIATE_ADD) {
2055 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002056 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002057 if (!d->must) {
2058 LOGMEM;
2059 goto error;
2060 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002061 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002062 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002063 d->must_size = c_must;
2064 } else { /* LY_DEVIATE_DEL */
2065 d->must = calloc(c_must, sizeof *d->must);
2066 }
Michal Vasko253035f2015-12-17 16:58:13 +01002067 if (!d->must) {
2068 LOGMEM;
2069 goto error;
2070 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002071 }
2072 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002073 /* replace unique is forbidden */
2074 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002075 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002076 goto error;
2077 }
2078
Radek Krejcieb00f512015-07-01 16:44:58 +02002079 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002080 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002081 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2082 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002083 goto error;
2084 }
2085
Michal Vasko60f4b452016-02-12 11:02:55 +01002086 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002087 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002089 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002090 list->unique = d->unique;
2091 d->unique = &list->unique[list->unique_size];
2092 d->unique_size = c_uniq;
2093 } else { /* LY_DEVIATE_DEL */
2094 d->unique = calloc(c_uniq, sizeof *d->unique);
2095 }
Michal Vasko253035f2015-12-17 16:58:13 +01002096 if (!d->unique) {
2097 LOGMEM;
2098 goto error;
2099 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002100 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002101 if (c_dflt) {
2102 if (d->mod == LY_DEVIATE_ADD) {
2103 /* check that there is no current value */
2104 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2105 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2106 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2107 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2108 goto error;
2109 }
2110
2111 /* check collision with mandatory/min-elements */
2112 if ((dev_target->flags & LYS_MAND_TRUE) ||
2113 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2114 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2115 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2116 "Adding the \"default\" statement is forbidden on %s statement.",
2117 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2118 goto error;
2119 }
2120 } else if (d->mod == LY_DEVIATE_RPL) {
2121 /* check that there was a value before */
2122 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2123 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2124 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2125 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2126 goto error;
2127 }
2128 }
2129
2130 if (dev_target->nodetype == LYS_LEAFLIST) {
2131 /* reallocate default list in the target */
2132 llist = (struct lys_node_leaflist *)dev_target;
2133 if (d->mod == LY_DEVIATE_ADD) {
2134 /* reallocate (enlarge) the unique array of the target */
2135 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2136 } else if (d->mod == LY_DEVIATE_RPL) {
2137 /* reallocate (replace) the unique array of the target */
2138 for (i = 0; i < llist->dflt_size; i++) {
2139 lydict_remove(llist->module->ctx, llist->dflt[i]);
2140 }
2141 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2142 llist->dflt_size = 0;
2143 }
2144 }
2145 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2146 if (!d->dflt) {
2147 LOGMEM;
2148 goto error;
2149 }
2150 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002151
2152 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002153 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002154 if (!strcmp(child->name, "must")) {
2155 if (d->mod == LY_DEVIATE_DEL) {
2156 if (fill_yin_must(module, child, &d->must[d->must_size])) {
2157 goto error;
2158 }
2159
2160 /* find must to delete, we are ok with just matching conditions */
2161 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002162 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002163 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002164 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002165 /* ... and maintain the array */
2166 (*trg_must_size)--;
2167 if (i != *trg_must_size) {
2168 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2169 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2170 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2171 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2172 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2173 }
2174 if (!(*trg_must_size)) {
2175 free(*trg_must);
2176 *trg_must = NULL;
2177 } else {
2178 (*trg_must)[*trg_must_size].expr = NULL;
2179 (*trg_must)[*trg_must_size].dsc = NULL;
2180 (*trg_must)[*trg_must_size].ref = NULL;
2181 (*trg_must)[*trg_must_size].eapptag = NULL;
2182 (*trg_must)[*trg_must_size].emsg = NULL;
2183 }
2184
2185 i = -1; /* set match flag */
2186 break;
2187 }
2188 }
2189 d->must_size++;
2190 if (i != -1) {
2191 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002192 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002193 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002194 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002195 goto error;
2196 }
2197 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002198 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2199 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002200 goto error;
2201 }
2202 (*trg_must_size)++;
2203 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002204
2205 /* check XPath dependencies again */
2206 if (*trg_must_size && unres_schema_add_node(dev_target->module, unres, dev_target, UNRES_XPATH, NULL)) {
2207 goto error;
2208 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002209 } else if (!strcmp(child->name, "unique")) {
2210 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002211 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002212 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002213 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002214 goto error;
2215 }
2216
2217 /* find unique structures to delete */
2218 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002219 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002220 continue;
2221 }
2222
Radek Krejci581ce772015-11-10 17:22:40 +01002223 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002224 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002225 break;
2226 }
2227 }
2228
Radek Krejci581ce772015-11-10 17:22:40 +01002229 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002231 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002232 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002233 }
2234 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 /* ... and maintain the array */
2236 list->unique_size--;
2237 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002238 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2239 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002240 }
2241
2242 if (!list->unique_size) {
2243 free(list->unique);
2244 list->unique = NULL;
2245 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002246 list->unique[list->unique_size].expr_size = 0;
2247 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002248 }
2249
2250 i = -1; /* set match flag */
2251 break;
2252 }
2253 }
2254
2255 d->unique_size++;
2256 if (i != -1) {
2257 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002258 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2259 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002260 goto error;
2261 }
2262 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002263 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002264 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002265 list->unique_size++;
2266 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002267 goto error;
2268 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002269 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002270 } else if (!strcmp(child->name, "default")) {
2271 GETVAL(value, child, "value");
2272 u = strlen(value);
2273 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2274
2275 if (dev_target->nodetype == LYS_CHOICE) {
2276 choice = (struct lys_node_choice *)dev_target;
2277 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2278 if (rc || !node) {
2279 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2280 goto error;
2281 }
2282 if (d->mod == LY_DEVIATE_DEL) {
2283 if (!choice->dflt || (choice->dflt != node)) {
2284 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2285 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2286 goto error;
2287 }
2288 } else { /* add or replace */
2289 choice->dflt = node;
2290 if (!choice->dflt) {
2291 /* default branch not found */
2292 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2293 goto error;
2294 }
2295 }
2296 } else if (dev_target->nodetype == LYS_LEAF) {
2297 leaf = (struct lys_node_leaf *)dev_target;
2298 if (d->mod == LY_DEVIATE_DEL) {
2299 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2300 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2301 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2302 goto error;
2303 }
2304 /* remove value */
2305 lydict_remove(ctx, leaf->dflt);
2306 leaf->dflt = NULL;
2307 } else { /* add (already checked) and replace */
2308 /* remove value */
2309 lydict_remove(ctx, leaf->dflt);
2310
2311 /* set new value */
2312 leaf->dflt = lydict_insert(ctx, value, u);
2313
2314 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2315 ly_set_add(dflt_check, dev_target, 0);
2316 }
2317 } else { /* LYS_LEAFLIST */
2318 llist = (struct lys_node_leaflist *)dev_target;
2319 if (d->mod == LY_DEVIATE_DEL) {
2320 /* find and remove the value in target list */
2321 for (i = 0; i < llist->dflt_size; i++) {
2322 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2323 /* match, remove the value */
2324 lydict_remove(llist->module->ctx, llist->dflt[i]);
2325 llist->dflt[i] = NULL;
2326 break;
2327 }
2328 }
2329 if (i == llist->dflt_size) {
2330 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2331 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2332 goto error;
2333 }
2334 } else {
2335 /* add or replace, anyway we place items into the deviate's list
2336 which propagates to the target */
2337 /* we just want to check that the value isn't already in the list */
2338 for (i = 0; i < llist->dflt_size; i++) {
2339 if (ly_strequal(llist->dflt[i], value, 1)) {
2340 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2341 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2342 goto error;
2343 }
2344 }
2345 /* store it in target node */
2346 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2347
2348 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2349 ly_set_add(dflt_check, dev_target, 0);
2350 }
2351 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002352 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002353 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002354
2355 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2356 /* consolidate the final list in the target after removing items from it */
2357 llist = (struct lys_node_leaflist *)dev_target;
2358 for (i = j = 0; j < llist->dflt_size; j++) {
2359 llist->dflt[i] = llist->dflt[j];
2360 if (llist->dflt[i]) {
2361 i++;
2362 }
2363 }
2364 llist->dflt_size = i + 1;
2365 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002366 }
2367
Michal Vasko43a1feb2016-03-07 12:03:02 +01002368 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002369 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002370 value = NULL;
2371 rc = EXIT_SUCCESS;
2372 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2373 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2374 rc = unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, value = leaf->dflt);
2375 } else { /* LYS_LEAFLIST */
2376 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2377 for (j = 0; j < llist->dflt_size; j++) {
2378 rc = unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, value = llist->dflt[j]);
2379 if (rc == -1) {
2380 break;
2381 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002382 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002383
2384 }
2385 if (rc == -1) {
2386 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2387 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2388 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2389 dev->target_name);
2390 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002391 }
2392 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002393
Radek Krejci27fe55e2016-09-13 17:13:35 +02002394 /* mark all the affected modules as deviated and implemented */
2395 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2396 mod = lys_node_module(parent);
2397 if (module != mod) {
2398 mod->deviated = 1;
2399 lys_set_implemented(mod);
2400 }
2401 }
2402
Radek Krejcid5a5c282016-08-15 15:38:08 +02002403 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002404 return EXIT_SUCCESS;
2405
2406error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002407 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002408 return EXIT_FAILURE;
2409}
2410
Michal Vasko0d343d12015-08-24 14:57:36 +02002411/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002412static int
Radek Krejcib8048692015-08-05 13:36:34 +02002413fill_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 +02002414 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002415{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002417 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002418 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002419 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002420
Michal Vasko591e0b22015-08-13 13:53:43 +02002421 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002422 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002423 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002424 if (!aug->target_name) {
2425 goto error;
2426 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002428
Michal Vasko1d87a922015-08-21 12:57:16 +02002429 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002430 goto error;
2431 }
2432
2433 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002434 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2435 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002436 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002437 continue;
2438 }
2439
Radek Krejci3cf9e222015-06-18 11:37:50 +02002440 if (!strcmp(child->name, "if-feature")) {
2441 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002442 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002443 } else if (!strcmp(child->name, "when")) {
2444 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002445 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002446 goto error;
2447 }
2448
2449 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002450 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002451 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002452 goto error;
2453 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002454 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002455 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002456
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002457 /* check allowed data sub-statements */
2458 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002460 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002461 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002462 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002463 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002464 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002465 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002466 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002467 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002468 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002469 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002470 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002471 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002472 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002473 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYXML, 0, unres);
2474 } else if (!strcmp(child->name, "anydata")) {
2475 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYDATA, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002476 } else if (!strcmp(child->name, "action")) {
2477 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02002478 } else if (!strcmp(child->name, "notification")) {
2479 node = read_yin_notif(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002480 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002481 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002482 goto error;
2483 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002484
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002486 goto error;
2487 }
2488
Radek Krejci1d82ef62015-08-07 14:44:40 +02002489 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002490 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002491 }
2492
2493 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002494 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2495 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002496 LOGMEM;
2497 goto error;
2498 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002499 }
2500
2501 LY_TREE_FOR_SAFE(yin->child, next, child) {
2502 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002503 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2504 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002505 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002506 goto error;
2507 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002508 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002509 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002510 }
2511
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002512 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002513 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002514 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002515 * when the uses does and cannot be resolved now for sure
2516 * (the grouping was not yet copied into uses).
2517 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002518 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002519 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002520 goto error;
2521 }
Michal Vasko49291b32015-08-06 09:49:41 +02002522 }
Radek Krejci106efc02015-06-10 14:36:27 +02002523
Michal Vasko508a50d2016-09-07 14:50:33 +02002524 /* check XPath dependencies */
2525 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2526 goto error;
2527 }
2528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002530
2531error:
2532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002534}
2535
Michal Vasko0d343d12015-08-24 14:57:36 +02002536/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002538fill_yin_refine(struct lys_node *uses, struct lyxml_elem *yin, struct lys_refine *rfn, struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002539{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002540 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 struct lyxml_elem *sub, *next;
2542 const char *value;
2543 char *endptr;
2544 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci200bf712016-08-16 17:11:04 +02002545 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 int r;
2547 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002548
Radek Krejci363bd4a2016-07-29 14:30:20 +02002549 assert(uses);
2550 module = uses->module; /* shorthand */
2551
Radek Krejci76512572015-08-04 09:47:08 +02002552 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 goto error;
2554 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002555
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002556 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002557 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002558 if (!rfn->target_name) {
2559 goto error;
2560 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002562 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002563 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2564 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002565 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002566 continue;
2567 }
2568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002569 /* limited applicability */
2570 if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002571 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 /* check possibility of statements combination */
2574 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002575 if (c_dflt) {
2576 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002577 if (module->version < 2) {
2578 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2579 goto error;
2580 }
Radek Krejci200bf712016-08-16 17:11:04 +02002581 rfn->target_type &= LYS_LEAFLIST;
2582 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002583 if (module->version < 2) {
2584 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2585 } else {
2586 /* YANG 1.1 */
2587 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2588 }
Radek Krejci200bf712016-08-16 17:11:04 +02002589 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002591 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2592 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002593 goto error;
2594 }
2595 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002596 if (module->version < 2) {
2597 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2598 } else {
2599 /* YANG 1.1 */
2600 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002603
Radek Krejci200bf712016-08-16 17:11:04 +02002604 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002605 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002606 } else if (!strcmp(sub->name, "mandatory")) {
2607 /* leaf, choice or anyxml */
2608 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002609 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002610 goto error;
2611 }
2612 /* just checking the flags in leaf is not sufficient, we would allow
2613 * multiple mandatory statements with the "false" value
2614 */
2615 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 /* check possibility of statements combination */
2618 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002619 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002620 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002621 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2622 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002623 goto error;
2624 }
2625 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002626 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002629 GETVAL(value, sub, "value");
2630 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002631 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002632 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002633 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002635 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 goto error;
2637 }
2638 } else if (!strcmp(sub->name, "min-elements")) {
2639 /* list or leaf-list */
2640 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002641 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002642 goto error;
2643 }
2644 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 /* check possibility of statements combination */
2647 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002648 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002650 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2651 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002652 goto error;
2653 }
2654 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002655 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002656 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 GETVAL(value, sub, "value");
2659 while (isspace(value[0])) {
2660 value++;
2661 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663 /* convert it to uint32_t */
2664 errno = 0;
2665 endptr = NULL;
2666 val = strtoul(value, &endptr, 10);
2667 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002668 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 goto error;
2670 }
2671 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002672 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002673 } else if (!strcmp(sub->name, "max-elements")) {
2674 /* list or leaf-list */
2675 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002676 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002677 goto error;
2678 }
2679 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002681 /* check possibility of statements combination */
2682 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002683 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002685 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2686 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002687 goto error;
2688 }
2689 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002690 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002692
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 GETVAL(value, sub, "value");
2694 while (isspace(value[0])) {
2695 value++;
2696 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002697
Radek Krejci0d7b2472016-02-12 11:11:03 +01002698 if (!strcmp(value, "unbounded")) {
2699 rfn->mod.list.max = 0;
2700 } else {
2701 /* convert it to uint32_t */
2702 errno = 0;
2703 endptr = NULL;
2704 val = strtoul(value, &endptr, 10);
2705 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002706 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002707 goto error;
2708 }
2709 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002711 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 } else if (!strcmp(sub->name, "presence")) {
2713 /* container */
2714 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002715 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002716 goto error;
2717 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002719 /* check possibility of statements combination */
2720 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002721 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002723 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2724 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 goto error;
2726 }
2727 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002728 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002729 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 GETVAL(value, sub, "value");
2732 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2733 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002734 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 /* check possibility of statements combination */
2736 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002737 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002739 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2740 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 goto error;
2742 }
2743 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002744 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002747 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002748 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002749
Radek Krejci363bd4a2016-07-29 14:30:20 +02002750 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2751 /* leaf, leaf-list, list, container or anyxml */
2752 /* check possibility of statements combination */
2753 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002754 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002755 if (!rfn->target_type) {
2756 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2757 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2758 goto error;
2759 }
2760 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002761 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002762 }
2763
2764 c_ftrs++;
2765 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002767 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002768 goto error;
2769 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002770
Michal Vasko345da0a2015-12-02 10:35:55 +01002771 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 /* process nodes with cardinality of 0..n */
2775 if (c_must) {
2776 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002777 if (!rfn->must) {
2778 LOGMEM;
2779 goto error;
2780 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002782 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002783 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002784 if (!rfn->iffeature) {
2785 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002786 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 }
Radek Krejci200bf712016-08-16 17:11:04 +02002789 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002790 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002791 if (!rfn->dflt) {
2792 LOGMEM;
2793 goto error;
2794 }
2795 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002796
Radek Krejci363bd4a2016-07-29 14:30:20 +02002797 LY_TREE_FOR(yin->child, sub) {
2798 if (!strcmp(sub->name, "if-feature")) {
2799 r = fill_yin_iffeature(uses, sub, &rfn->iffeature[rfn->iffeature_size], unres);
2800 rfn->iffeature_size++;
2801 if (r) {
2802 goto error;
2803 }
Radek Krejci200bf712016-08-16 17:11:04 +02002804 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002805 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2806 rfn->must_size++;
2807 if (r) {
2808 goto error;
2809 }
Radek Krejci200bf712016-08-16 17:11:04 +02002810 } else { /* default */
2811 GETVAL(value, sub, "value");
2812
2813 /* check for duplicity */
2814 for (r = 0; r < rfn->dflt_size; r++) {
2815 if (ly_strequal(rfn->dflt[r], value, 1)) {
2816 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2817 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2818 goto error;
2819 }
2820 }
2821 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02002822 }
2823 }
2824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002826
2827error:
2828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002829 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002830}
2831
Michal Vasko0d343d12015-08-24 14:57:36 +02002832/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833static int
Radek Krejcib8048692015-08-05 13:36:34 +02002834fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002835{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 struct lyxml_elem *child;
2837 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002840 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2841 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002842 continue;
2843 }
2844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002845 if (!strcmp(child->name, "prefix")) {
2846 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002847 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 goto error;
2849 }
2850 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2851 } else if (!strcmp(child->name, "revision-date")) {
2852 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002853 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2854 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 }
2856 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002857 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002858 goto error;
2859 }
2860 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002861 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002862 if (imp->dsc) {
2863 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2864 goto error;
2865 }
2866 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2867 if (!imp->dsc) {
2868 goto error;
2869 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002870 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002871 if (imp->ref) {
2872 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2873 goto error;
2874 }
2875 imp->ref = read_yin_subnode(module->ctx, child, "text");
2876 if (!imp->ref) {
2877 goto error;
2878 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002879 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002880 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 goto error;
2882 }
2883 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 /* check mandatory information */
2886 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002887 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 goto error;
2889 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002891 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002892
Pavol Vicane994fda2016-03-22 10:47:58 +01002893 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002894
2895error:
2896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002898}
2899
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002900/* logs directly
2901 * returns:
2902 * 0 - inc successfully filled
2903 * -1 - error, inc is cleaned
2904 * 1 - duplication, ignore the inc structure, inc is cleaned
2905 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002907fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2908 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002909{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 struct lyxml_elem *child;
2911 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002914 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2915 /* garbage */
2916 continue;
2917 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002918 if (!strcmp(child->name, "revision-date")) {
2919 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002920 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 goto error;
2922 }
2923 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002924 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 goto error;
2926 }
2927 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002928 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002929 if (inc->dsc) {
2930 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2931 goto error;
2932 }
2933 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2934 if (!inc->dsc) {
2935 goto error;
2936 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002937 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002938 if (inc->ref) {
2939 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2940 goto error;
2941 }
2942 inc->ref = read_yin_subnode(module->ctx, child, "text");
2943 if (!inc->ref) {
2944 goto error;
2945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002947 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002948 goto error;
2949 }
2950 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002953
Pavol Vican0adf01d2016-03-22 12:29:33 +01002954 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002955
2956error:
2957
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002958 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002959}
2960
Michal Vasko0d343d12015-08-24 14:57:36 +02002961/* logs directly
2962 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002963 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002964 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002965 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002966 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967static int
Radek Krejcib8048692015-08-05 13:36:34 +02002968read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002969 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002970{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 const char *value;
2972 struct lyxml_elem *sub, *next;
2973 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002976 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 if (opt & OPT_IDENT) {
2980 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002981 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002982 goto error;
2983 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002984 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002986
Radek Krejci6764bb32015-07-03 15:16:04 +02002987 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002988 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002989 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002990 }
2991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 /* process local parameters */
2993 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002994 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002995 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002996 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002997 continue;
2998 }
2999 if (strcmp(sub->ns->value, LY_NSYIN)) {
3000 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02003001 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003002 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003003 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02003004 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003005 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02003006 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003007 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02003008 goto error;
3009 }
3010 }
3011
3012 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003013 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003014 continue;
3015 }
3016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003018 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003019 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 goto error;
3021 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003022 node->dsc = read_yin_subnode(ctx, sub, "text");
3023 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003024 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 }
3026 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003027 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003028 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 goto error;
3030 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003031 node->ref = read_yin_subnode(ctx, sub, "text");
3032 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003033 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 }
3035 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003036 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003037 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 goto error;
3039 }
3040 GETVAL(value, sub, "value");
3041 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003042 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003044 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003046 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003048 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003049 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 }
3051 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003052 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003053 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003054 goto error;
3055 }
3056 GETVAL(value, sub, "value");
3057 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003058 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003060 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003062 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003063 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02003065 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003067 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 continue;
3069 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003070 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072
Radek Krejci1d82ef62015-08-07 14:44:40 +02003073 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003074 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02003075 if (parent && (parent->flags & LYS_CONFIG_R)) {
3076 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 } else {
3078 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003079 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 }
3081 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003084
3085error:
3086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003088}
3089
Michal Vasko0d343d12015-08-24 14:57:36 +02003090/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003091static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003092read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003093{
Radek Krejci76512572015-08-04 09:47:08 +02003094 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003095 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003096 const char *value;
3097
3098 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003099 if (!retval) {
3100 LOGMEM;
3101 return NULL;
3102 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003103
3104 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003105 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003106 if (!retval->cond) {
3107 goto error;
3108 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003109
Radek Krejci73adb602015-07-02 18:07:40 +02003110 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003111 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3112 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003113 continue;
3114 }
3115
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003116 if (!strcmp(child->name, "description")) {
3117 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003118 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003119 goto error;
3120 }
3121 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3122 if (!retval->dsc) {
3123 goto error;
3124 }
3125 } else if (!strcmp(child->name, "reference")) {
3126 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003127 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003128 goto error;
3129 }
3130 retval->ref = read_yin_subnode(module->ctx, child, "text");
3131 if (!retval->ref) {
3132 goto error;
3133 }
3134 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003135 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003136 goto error;
3137 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003138 }
3139
3140 return retval;
3141
3142error:
3143
Michal Vasko0308dd62015-10-07 09:14:40 +02003144 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003145 return NULL;
3146}
3147
Michal Vasko0d343d12015-08-24 14:57:36 +02003148/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003149static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003150read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3151 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003152{
Michal Vasko29fc0182015-08-24 15:02:39 +02003153 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003154 struct lys_node_case *cs;
3155 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02003156 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003157
Radek Krejcie867c852015-08-27 09:52:34 +02003158 /* init */
3159 memset(&root, 0, sizeof root);
3160
Radek Krejci1d82ef62015-08-07 14:44:40 +02003161 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003162 if (!cs) {
3163 LOGMEM;
3164 return NULL;
3165 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003166 cs->nodetype = LYS_CASE;
3167 cs->prev = (struct lys_node *)cs;
3168 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003169
Radek Krejci6a113852015-07-03 16:04:20 +02003170 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 goto error;
3172 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003173
Radek Krejcia9544502015-08-14 08:24:29 +02003174 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3175
Michal Vasko3a0043f2015-08-12 12:11:30 +02003176 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003177 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003178 goto error;
3179 }
3180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 /* process choice's specific children */
3182 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003183 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3184 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003185 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003186 continue;
3187 }
3188
Michal Vasko29fc0182015-08-24 15:02:39 +02003189 if (!strcmp(sub->name, "container") ||
3190 !strcmp(sub->name, "leaf-list") ||
3191 !strcmp(sub->name, "leaf") ||
3192 !strcmp(sub->name, "list") ||
3193 !strcmp(sub->name, "uses") ||
3194 !strcmp(sub->name, "choice") ||
3195 !strcmp(sub->name, "anyxml")) {
3196
Michal Vaskof3930de2015-10-22 12:03:59 +02003197 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003198 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003199 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003200 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01003201 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02003202 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003203 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003204 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003205 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003206 goto error;
3207 }
3208
Radek Krejci1d82ef62015-08-07 14:44:40 +02003209 cs->when = read_yin_when(module, sub);
3210 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003211 goto error;
3212 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003213
Michal Vasko345da0a2015-12-02 10:35:55 +01003214 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003216 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003217 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003220
Radek Krejci3cf9e222015-06-18 11:37:50 +02003221 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003222 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3223 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003224 LOGMEM;
3225 goto error;
3226 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003227 }
Radek Krejci73adb602015-07-02 18:07:40 +02003228 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003229 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
3230 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003231 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003232 goto error;
3233 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 }
Radek Krejcib388c152015-06-04 17:03:03 +02003235
Michal Vasko29fc0182015-08-24 15:02:39 +02003236 /* last part - process data nodes */
3237 LY_TREE_FOR_SAFE(root.child, next, sub) {
3238 if (!strcmp(sub->name, "container")) {
3239 node = read_yin_container(module, retval, sub, resolve, unres);
3240 } else if (!strcmp(sub->name, "leaf-list")) {
3241 node = read_yin_leaflist(module, retval, sub, resolve, unres);
3242 } else if (!strcmp(sub->name, "leaf")) {
3243 node = read_yin_leaf(module, retval, sub, resolve, unres);
3244 } else if (!strcmp(sub->name, "list")) {
3245 node = read_yin_list(module, retval, sub, resolve, unres);
3246 } else if (!strcmp(sub->name, "choice")) {
3247 node = read_yin_choice(module, retval, sub, resolve, unres);
3248 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003249 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003250 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003251 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
3252 } else if (!strcmp(sub->name, "anydata")) {
3253 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003254 }
3255 if (!node) {
3256 goto error;
3257 }
3258
Michal Vasko345da0a2015-12-02 10:35:55 +01003259 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003260 }
3261
Michal Vasko508a50d2016-09-07 14:50:33 +02003262 /* check XPath dependencies */
3263 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3264 goto error;
3265 }
3266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003268
3269error:
3270
Michal Vasko29fc0182015-08-24 15:02:39 +02003271 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003272 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003273 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003274 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003276 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003277}
3278
Michal Vasko0d343d12015-08-24 14:57:36 +02003279/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003280static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02003281read_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 +02003282{
Radek Krejci629cdef2016-06-06 15:06:36 +02003283 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003285 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003286 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003287 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02003288 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003291 if (!choice) {
3292 LOGMEM;
3293 return NULL;
3294 }
Radek Krejci76512572015-08-04 09:47:08 +02003295 choice->nodetype = LYS_CHOICE;
3296 choice->prev = (struct lys_node *)choice;
3297 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003298
Michal Vaskoe0c59842015-09-24 13:52:20 +02003299 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3300 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 goto error;
3302 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003303
Radek Krejcia9544502015-08-14 08:24:29 +02003304 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3305
Michal Vasko3a0043f2015-08-12 12:11:30 +02003306 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003307 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003308 goto error;
3309 }
3310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 /* process choice's specific children */
3312 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003313 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3314 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003315 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003316 continue;
3317 }
3318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003320 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 goto error;
3322 }
3323 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003324 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 goto error;
3326 }
3327 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003328 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 goto error;
3330 }
3331 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003332 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003333 goto error;
3334 }
3335 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003336 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 goto error;
3338 }
3339 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003340 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres))) {
3341 goto error;
3342 }
3343 } else if (!strcmp(sub->name, "anydata")) {
3344 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 goto error;
3346 }
3347 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003348 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003349 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 goto error;
3351 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003352 dflt = sub;
3353 lyxml_unlink_elem(ctx, dflt, 0);
3354
Radek Krejcif9a312c2016-06-06 15:14:30 +02003355 continue;
3356 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 } else if (!strcmp(sub->name, "mandatory")) {
3359 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003360 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 goto error;
3362 }
3363 /* just checking the flags in leaf is not sufficient, we would allow
3364 * multiple mandatory statements with the "false" value
3365 */
3366 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 GETVAL(value, sub, "value");
3369 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003370 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003371 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003372 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003373 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003374 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 goto error;
3376 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003377 } else if (!strcmp(sub->name, "when")) {
3378 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003379 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003380 goto error;
3381 }
3382
3383 choice->when = read_yin_when(module, sub);
3384 if (!choice->when) {
3385 goto error;
3386 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003387 } else if (!strcmp(sub->name, "if-feature")) {
3388 c_ftrs++;
3389
Michal Vasko345da0a2015-12-02 10:35:55 +01003390 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003391 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003392 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
3393 if (!(node = read_yin_choice(module, retval, sub, resolve, unres))) {
3394 goto error;
3395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003397 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003400
Radek Krejci1d82ef62015-08-07 14:44:40 +02003401 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003402 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003404
Radek Krejci3cf9e222015-06-18 11:37:50 +02003405 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003406 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3407 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003408 LOGMEM;
3409 goto error;
3410 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003411 }
3412
Radek Krejci73adb602015-07-02 18:07:40 +02003413 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003414 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
3415 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003416 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003417 goto error;
3418 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003419 }
3420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003422 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003423 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
3424 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 goto error;
3426 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003429 if (dflt) {
3430 GETVAL(value, dflt, "value");
3431 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003432 goto error;
3433 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003434 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003436
Michal Vasko508a50d2016-09-07 14:50:33 +02003437 /* check XPath dependencies */
3438 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3439 goto error;
3440 }
3441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003443
3444error:
3445
Radek Krejci629cdef2016-06-06 15:06:36 +02003446 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003447 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003450}
3451
Michal Vasko0d343d12015-08-24 14:57:36 +02003452/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003453static struct lys_node *
Radek Krejcibf2abff2016-08-23 15:51:52 +02003454read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type, int resolve,
3455 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003456{
Radek Krejci76512572015-08-04 09:47:08 +02003457 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003458 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 struct lyxml_elem *sub, *next;
3460 const char *value;
3461 int r;
3462 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003463 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003466 if (!anyxml) {
3467 LOGMEM;
3468 return NULL;
3469 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003470 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003471 anyxml->prev = (struct lys_node *)anyxml;
3472 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003473
Michal Vaskoe0c59842015-09-24 13:52:20 +02003474 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3475 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 goto error;
3477 }
Radek Krejci863c2852015-06-03 15:47:11 +02003478
Radek Krejcia9544502015-08-14 08:24:29 +02003479 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003480
Radek Krejciadb30652016-07-11 15:27:07 +02003481 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003482 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003483 goto error;
3484 }
3485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003487 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3488 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003489 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003490 continue;
3491 }
3492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 if (!strcmp(sub->name, "mandatory")) {
3494 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003495 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 goto error;
3497 }
3498 /* just checking the flags in leaf is not sufficient, we would allow
3499 * multiple mandatory statements with the "false" value
3500 */
3501 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003503 GETVAL(value, sub, "value");
3504 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003505 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003506 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003507 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003508 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003509 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 goto error;
3511 }
3512 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003513 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003514 } else if (!strcmp(sub->name, "when")) {
3515 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003516 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003517 goto error;
3518 }
3519
3520 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003521 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003522 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003523 goto error;
3524 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003525 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 } else if (!strcmp(sub->name, "must")) {
3527 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003528 } else if (!strcmp(sub->name, "if-feature")) {
3529 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003532 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 }
3535 }
Radek Krejci863c2852015-06-03 15:47:11 +02003536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 /* middle part - process nodes with cardinality of 0..n */
3538 if (c_must) {
3539 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003540 if (!anyxml->must) {
3541 LOGMEM;
3542 goto error;
3543 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003545 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003546 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3547 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003548 LOGMEM;
3549 goto error;
3550 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003551 }
Radek Krejci863c2852015-06-03 15:47:11 +02003552
Radek Krejci73adb602015-07-02 18:07:40 +02003553 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003555 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3556 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 if (r) {
3558 goto error;
3559 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003560 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003561 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3562 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003563 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003564 goto error;
3565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 }
Radek Krejci863c2852015-06-03 15:47:11 +02003568
Michal Vasko508a50d2016-09-07 14:50:33 +02003569 /* check XPath dependencies */
3570 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3571 goto error;
3572 }
3573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003575
3576error:
3577
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003578 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003581}
3582
Michal Vasko0d343d12015-08-24 14:57:36 +02003583/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003584static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003585read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003586 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003587{
Radek Krejci76512572015-08-04 09:47:08 +02003588 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003589 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 struct lyxml_elem *sub, *next;
3591 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003592 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003593 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003596 if (!leaf) {
3597 LOGMEM;
3598 return NULL;
3599 }
Radek Krejci76512572015-08-04 09:47:08 +02003600 leaf->nodetype = LYS_LEAF;
3601 leaf->prev = (struct lys_node *)leaf;
3602 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003603
Michal Vaskoe0c59842015-09-24 13:52:20 +02003604 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3605 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 goto error;
3607 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003608
Radek Krejcia9544502015-08-14 08:24:29 +02003609 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003610
Radek Krejciadb30652016-07-11 15:27:07 +02003611 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003612 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003613 goto error;
3614 }
3615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003617 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3618 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003619 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003620 continue;
3621 }
3622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003624 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003625 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 goto error;
3627 }
Michal Vasko88c29542015-11-27 14:57:53 +01003628 /* HACK for unres */
3629 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003630 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko3767fb22016-07-21 12:10:57 +02003631 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003632 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 goto error;
3634 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003635 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 } else if (!strcmp(sub->name, "default")) {
3637 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003638 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 goto error;
3640 }
3641 GETVAL(value, sub, "value");
3642 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3643 } else if (!strcmp(sub->name, "units")) {
3644 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003645 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003646 goto error;
3647 }
3648 GETVAL(value, sub, "name");
3649 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3650 } else if (!strcmp(sub->name, "mandatory")) {
3651 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 goto error;
3654 }
3655 /* just checking the flags in leaf is not sufficient, we would allow
3656 * multiple mandatory statements with the "false" value
3657 */
3658 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 GETVAL(value, sub, "value");
3661 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003662 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003663 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003664 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003665 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003666 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 goto error;
3668 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003669 } else if (!strcmp(sub->name, "when")) {
3670 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003671 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003672 goto error;
3673 }
3674
3675 leaf->when = read_yin_when(module, sub);
3676 if (!leaf->when) {
3677 goto error;
3678 }
3679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003681 c_must++;
3682 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003683 } else if (!strcmp(sub->name, "if-feature")) {
3684 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003688 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003689 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003691
Michal Vasko88c29542015-11-27 14:57:53 +01003692 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003696 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003697 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 goto error;
3699 }
Michal Vasko478c4652016-07-21 12:55:01 +02003700 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3701 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3702 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3703 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3704 goto error;
3705 }
3706
3707 /* check default value (if not defined, there still could be some restrictions
3708 * that need to be checked against a default value from a derived type) */
3709 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3710 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 /* middle part - process nodes with cardinality of 0..n */
3714 if (c_must) {
3715 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003716 if (!leaf->must) {
3717 LOGMEM;
3718 goto error;
3719 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003721 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003722 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3723 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003724 LOGMEM;
3725 goto error;
3726 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003727 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003728
Radek Krejci73adb602015-07-02 18:07:40 +02003729 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003731 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3732 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 if (r) {
3734 goto error;
3735 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003736 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003737 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3738 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003739 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003740 goto error;
3741 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003744
Michal Vasko508a50d2016-09-07 14:50:33 +02003745 /* check XPath dependencies */
3746 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3747 goto error;
3748 }
3749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003750 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003751
3752error:
3753
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003754 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757}
3758
Michal Vasko0d343d12015-08-24 14:57:36 +02003759/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003760static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003761read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003762 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763{
Radek Krejci76512572015-08-04 09:47:08 +02003764 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003765 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 struct lyxml_elem *sub, *next;
3767 const char *value;
3768 char *endptr;
3769 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003770 int r, has_type = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003771 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003775 if (!llist) {
3776 LOGMEM;
3777 return NULL;
3778 }
Radek Krejci76512572015-08-04 09:47:08 +02003779 llist->nodetype = LYS_LEAFLIST;
3780 llist->prev = (struct lys_node *)llist;
3781 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003782
Michal Vaskoe0c59842015-09-24 13:52:20 +02003783 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3784 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003785 goto error;
3786 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003787
Radek Krejcia9544502015-08-14 08:24:29 +02003788 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003789
Radek Krejciadb30652016-07-11 15:27:07 +02003790 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003791 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003792 goto error;
3793 }
3794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003796 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3797 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003798 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003799 continue;
3800 }
3801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003803 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003804 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 goto error;
3806 }
Michal Vasko88c29542015-11-27 14:57:53 +01003807 /* HACK for unres */
3808 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003809 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko3767fb22016-07-21 12:10:57 +02003810 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003811 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 goto error;
3813 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003814 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 } else if (!strcmp(sub->name, "units")) {
3816 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003817 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 goto error;
3819 }
3820 GETVAL(value, sub, "name");
3821 llist->units = lydict_insert(module->ctx, value, strlen(value));
3822 } else if (!strcmp(sub->name, "ordered-by")) {
3823 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003824 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003825 goto error;
3826 }
3827 /* just checking the flags in llist is not sufficient, we would
3828 * allow multiple ordered-by statements with the "system" value
3829 */
3830 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003831
Radek Krejci1574a8d2015-08-03 14:16:52 +02003832 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003833 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3834 * state data
3835 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003836 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 continue;
3838 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 GETVAL(value, sub, "value");
3841 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003842 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003844 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003846 } /* else system is the default value, so we can ignore it */
3847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 } else if (!strcmp(sub->name, "must")) {
3849 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003850 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003851 } else if (!strcmp(sub->name, "if-feature")) {
3852 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003854 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
3855 c_dflt++;
3856 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 } else if (!strcmp(sub->name, "min-elements")) {
3859 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003860 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 goto error;
3862 }
3863 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 GETVAL(value, sub, "value");
3866 while (isspace(value[0])) {
3867 value++;
3868 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 /* convert it to uint32_t */
3871 errno = 0;
3872 endptr = NULL;
3873 val = strtoul(value, &endptr, 10);
3874 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003875 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 goto error;
3877 }
3878 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003879 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003880 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3881 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003882 goto error;
3883 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 } else if (!strcmp(sub->name, "max-elements")) {
3885 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003886 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 goto error;
3888 }
3889 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003891 GETVAL(value, sub, "value");
3892 while (isspace(value[0])) {
3893 value++;
3894 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003895
Radek Krejci0d7b2472016-02-12 11:11:03 +01003896 if (!strcmp(value, "unbounded")) {
3897 llist->max = 0;
3898 } else {
3899 /* convert it to uint32_t */
3900 errno = 0;
3901 endptr = NULL;
3902 val = strtoul(value, &endptr, 10);
3903 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003904 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003905 goto error;
3906 }
3907 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003908 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003909 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3910 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003911 goto error;
3912 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003914 } else if (!strcmp(sub->name, "when")) {
3915 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003916 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003917 goto error;
3918 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003919
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003920 llist->when = read_yin_when(module, sub);
3921 if (!llist->when) {
3922 goto error;
3923 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003925 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003927 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003928
Michal Vasko88c29542015-11-27 14:57:53 +01003929 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003933 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003934 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 goto error;
3936 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 /* middle part - process nodes with cardinality of 0..n */
3939 if (c_must) {
3940 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003941 if (!llist->must) {
3942 LOGMEM;
3943 goto error;
3944 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003946 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003947 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3948 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003949 LOGMEM;
3950 goto error;
3951 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003952 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003953 if (c_dflt) {
3954 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
3955 if (!llist->dflt) {
3956 LOGMEM;
3957 goto error;
3958 }
3959 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003960
Radek Krejci73adb602015-07-02 18:07:40 +02003961 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003963 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3964 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 if (r) {
3966 goto error;
3967 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003968 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003969 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3970 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003971 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003972 goto error;
3973 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003974 } else if (!strcmp(sub->name, "default")) {
3975 GETVAL(value, sub, "value");
3976
Radek Krejciac1a52c2016-09-15 14:42:40 +02003977 /* check for duplicity in case of configuration data,
3978 * in case of status data duplicities are allowed */
3979 if (llist->flags & LYS_CONFIG_W) {
3980 for (r = 0; r < llist->dflt_size; r++) {
3981 if (ly_strequal(llist->dflt[r], value, 1)) {
3982 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3983 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3984 goto error;
3985 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003986 }
3987 }
3988 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
3989 }
3990 }
3991
3992 if (llist->dflt_size && llist->min) {
Radek Krejci200bf712016-08-16 17:11:04 +02003993 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "leaf-list");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003994 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3995 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
3996 goto error;
3997 }
3998
3999 /* check default value (if not defined, there still could be some restrictions
4000 * that need to be checked against a default value from a derived type) */
4001 for (r = 0; r < llist->dflt_size; r++) {
4002 if (unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, llist->dflt[r]) == -1) {
4003 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004006
Michal Vasko508a50d2016-09-07 14:50:33 +02004007 /* check XPath dependencies */
4008 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4009 goto error;
4010 }
4011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004013
4014error:
4015
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004016 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004018 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004019}
4020
Michal Vasko0d343d12015-08-24 14:57:36 +02004021/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004022static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004023read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4024 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004025{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004026 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004027 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004029 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004030 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004031 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02004032 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 char *auxs;
4034 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004036 /* init */
4037 memset(&root, 0, sizeof root);
4038 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004040 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004041 if (!list) {
4042 LOGMEM;
4043 return NULL;
4044 }
Radek Krejci76512572015-08-04 09:47:08 +02004045 list->nodetype = LYS_LIST;
4046 list->prev = (struct lys_node *)list;
4047 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004048
Michal Vaskoe0c59842015-09-24 13:52:20 +02004049 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
4050 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 goto error;
4052 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004053
Radek Krejcia9544502015-08-14 08:24:29 +02004054 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4055
Radek Krejciadb30652016-07-11 15:27:07 +02004056 /* insert the node into the schema tree */
4057 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4058 goto error;
4059 }
4060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 /* process list's specific children */
4062 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004063 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4064 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004065 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004066 continue;
4067 }
4068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004069 /* data statements */
4070 if (!strcmp(sub->name, "container") ||
4071 !strcmp(sub->name, "leaf-list") ||
4072 !strcmp(sub->name, "leaf") ||
4073 !strcmp(sub->name, "list") ||
4074 !strcmp(sub->name, "choice") ||
4075 !strcmp(sub->name, "uses") ||
4076 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004077 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004078 !strcmp(sub->name, "action") ||
4079 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004080 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004081 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004083 /* array counters */
4084 } else if (!strcmp(sub->name, "key")) {
4085 /* check cardinality 0..1 */
4086 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004087 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004088 goto error;
4089 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02004090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 /* count the number of keys */
4092 GETVAL(value, sub, "value");
4093 key_str = value;
4094 while ((value = strpbrk(value, " \t\n"))) {
4095 list->keys_size++;
4096 while (isspace(*value)) {
4097 value++;
4098 }
4099 }
4100 list->keys_size++;
4101 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004102 if (!list->keys) {
4103 LOGMEM;
4104 goto error;
4105 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106 } else if (!strcmp(sub->name, "unique")) {
4107 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004108 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004109 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004110 } else if (!strcmp(sub->name, "typedef")) {
4111 c_tpdf++;
4112 } else if (!strcmp(sub->name, "must")) {
4113 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004114 } else if (!strcmp(sub->name, "if-feature")) {
4115 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004117 /* optional stetments */
4118 } else if (!strcmp(sub->name, "ordered-by")) {
4119 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004120 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004121 goto error;
4122 }
4123 /* just checking the flags in llist is not sufficient, we would
4124 * allow multiple ordered-by statements with the "system" value
4125 */
4126 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004127
Radek Krejci1574a8d2015-08-03 14:16:52 +02004128 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004129 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4130 * state data
4131 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004132 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004133 continue;
4134 }
Radek Krejci345ad742015-06-03 11:04:18 +02004135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004136 GETVAL(value, sub, "value");
4137 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004138 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004139 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004140 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004141 goto error;
4142 }
4143 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004144 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 } else if (!strcmp(sub->name, "min-elements")) {
4146 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004147 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004148 goto error;
4149 }
4150 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004152 GETVAL(value, sub, "value");
4153 while (isspace(value[0])) {
4154 value++;
4155 }
Radek Krejci345ad742015-06-03 11:04:18 +02004156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 /* convert it to uint32_t */
4158 errno = 0;
4159 auxs = NULL;
4160 val = strtoul(value, &auxs, 10);
4161 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004162 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004163 goto error;
4164 }
4165 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004166 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004167 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4168 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004169 lyxml_free(module->ctx, sub);
4170 goto error;
4171 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004172 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004173 } else if (!strcmp(sub->name, "max-elements")) {
4174 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004175 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004176 goto error;
4177 }
4178 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 GETVAL(value, sub, "value");
4181 while (isspace(value[0])) {
4182 value++;
4183 }
Radek Krejci345ad742015-06-03 11:04:18 +02004184
Radek Krejci0d7b2472016-02-12 11:11:03 +01004185 if (!strcmp(value, "unbounded")) {
4186 list->max = 0;;
4187 } else {
4188 /* convert it to uint32_t */
4189 errno = 0;
4190 auxs = NULL;
4191 val = strtoul(value, &auxs, 10);
4192 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004193 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004194 goto error;
4195 }
4196 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004197 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004198 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4199 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004200 goto error;
4201 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004202 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004203 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004204 } else if (!strcmp(sub->name, "when")) {
4205 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004206 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004207 goto error;
4208 }
4209
4210 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004211 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004212 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004213 goto error;
4214 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004215 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004216 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004217 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004218 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004219 }
4220 }
Radek Krejci345ad742015-06-03 11:04:18 +02004221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004222 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004223 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004224 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004225 goto error;
4226 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004228 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4229 if (c_tpdf) {
4230 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004231 if (!list->tpdf) {
4232 LOGMEM;
4233 goto error;
4234 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004235 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004236 if (c_must) {
4237 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004238 if (!list->must) {
4239 LOGMEM;
4240 goto error;
4241 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004242 }
4243 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004244 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4245 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004246 LOGMEM;
4247 goto error;
4248 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004249 }
Radek Krejci73adb602015-07-02 18:07:40 +02004250 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004251 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004252 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4253 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 if (r) {
4255 goto error;
4256 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004257 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004258 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
4259 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004260 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004261 goto error;
4262 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004263 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004264 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4265 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004266 if (r) {
4267 goto error;
4268 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004269 }
4270 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004272 /* last part - process data nodes */
4273 LY_TREE_FOR_SAFE(root.child, next, sub) {
4274 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004275 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004277 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004279 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004281 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004283 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004284 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004285 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004287 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004288 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004289 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4290 } else if (!strcmp(sub->name, "anydata")) {
4291 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004292 } else if (!strcmp(sub->name, "action")) {
4293 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004294 } else if (!strcmp(sub->name, "notification")) {
4295 node = read_yin_notif(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004296 } else {
4297 LOGINT;
4298 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004300 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004301 goto error;
4302 }
Radek Krejci73adb602015-07-02 18:07:40 +02004303
Michal Vasko345da0a2015-12-02 10:35:55 +01004304 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004305 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004306
Radek Krejci461efb92016-02-12 15:52:18 +01004307 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004308 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004309 goto error;
4310 }
4311 } /* 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 +02004312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 /* process unique statements */
4314 if (c_uniq) {
4315 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004316 if (!list->unique) {
4317 LOGMEM;
4318 goto error;
4319 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004320
Radek Krejci461efb92016-02-12 15:52:18 +01004321 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4322 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4323 list->unique_size++;
4324 if (r) {
4325 goto error;
4326 }
4327
4328 lyxml_free(module->ctx, sub);
4329 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004331
Michal Vasko508a50d2016-09-07 14:50:33 +02004332 /* check XPath dependencies */
4333 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4334 goto error;
4335 }
4336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004338
4339error:
4340
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004341 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004343 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 }
4345 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004346 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004347 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004349 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004350}
4351
Michal Vasko0d343d12015-08-24 14:57:36 +02004352/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004353static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004354read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4355 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004356{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004358 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004359 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004360 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004361 const char *value;
4362 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004363 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004365 /* init */
4366 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004368 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004369 if (!cont) {
4370 LOGMEM;
4371 return NULL;
4372 }
Radek Krejci76512572015-08-04 09:47:08 +02004373 cont->nodetype = LYS_CONTAINER;
4374 cont->prev = (struct lys_node *)cont;
4375 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004376
Michal Vaskoe0c59842015-09-24 13:52:20 +02004377 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
4378 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004379 goto error;
4380 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004381
Radek Krejcia9544502015-08-14 08:24:29 +02004382 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4383
Radek Krejciadb30652016-07-11 15:27:07 +02004384 /* insert the node into the schema tree */
4385 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4386 goto error;
4387 }
4388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004389 /* process container's specific children */
4390 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02004391 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004392 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004393 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004394 continue;
4395 }
4396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004397 if (!strcmp(sub->name, "presence")) {
4398 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004399 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 goto error;
4401 }
4402 GETVAL(value, sub, "value");
4403 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004404
Michal Vasko345da0a2015-12-02 10:35:55 +01004405 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004406 } else if (!strcmp(sub->name, "when")) {
4407 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004408 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004409 goto error;
4410 }
4411
4412 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004413 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004414 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004415 goto error;
4416 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004417 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 /* data statements */
4420 } else if (!strcmp(sub->name, "container") ||
4421 !strcmp(sub->name, "leaf-list") ||
4422 !strcmp(sub->name, "leaf") ||
4423 !strcmp(sub->name, "list") ||
4424 !strcmp(sub->name, "choice") ||
4425 !strcmp(sub->name, "uses") ||
4426 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004427 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004428 !strcmp(sub->name, "action") ||
4429 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004430 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004431 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 /* array counters */
4434 } else if (!strcmp(sub->name, "typedef")) {
4435 c_tpdf++;
4436 } else if (!strcmp(sub->name, "must")) {
4437 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004438 } else if (!strcmp(sub->name, "if-feature")) {
4439 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004441 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004443 }
4444 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4447 if (c_tpdf) {
4448 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004449 if (!cont->tpdf) {
4450 LOGMEM;
4451 goto error;
4452 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 }
4454 if (c_must) {
4455 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004456 if (!cont->must) {
4457 LOGMEM;
4458 goto error;
4459 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004461 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004462 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4463 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004464 LOGMEM;
4465 goto error;
4466 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004467 }
Radek Krejci800af702015-06-02 13:46:01 +02004468
Radek Krejci73adb602015-07-02 18:07:40 +02004469 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004471 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4472 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 if (r) {
4474 goto error;
4475 }
4476 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004477 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4478 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 if (r) {
4480 goto error;
4481 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004482 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004483 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
4484 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004485 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004486 goto error;
4487 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004491 /* last part - process data nodes */
4492 LY_TREE_FOR_SAFE(root.child, next, sub) {
4493 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004494 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004496 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004498 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004500 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004501 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004502 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004504 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004505 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004506 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004508 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4509 } else if (!strcmp(sub->name, "anydata")) {
4510 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004511 } else if (!strcmp(sub->name, "action")) {
4512 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004513 } else if (!strcmp(sub->name, "notification")) {
4514 node = read_yin_notif(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004516 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 goto error;
4518 }
Radek Krejci73adb602015-07-02 18:07:40 +02004519
Michal Vasko345da0a2015-12-02 10:35:55 +01004520 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004522
Michal Vasko508a50d2016-09-07 14:50:33 +02004523 /* check XPath dependencies */
4524 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4525 goto error;
4526 }
4527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004529
4530error:
4531
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004532 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004534 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004538}
4539
Michal Vasko0d343d12015-08-24 14:57:36 +02004540/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004541static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02004542read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004543 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004544{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004545 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004546 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004547 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004548 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 int r;
4550 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004552 /* init */
4553 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004556 if (!grp) {
4557 LOGMEM;
4558 return NULL;
4559 }
Radek Krejci76512572015-08-04 09:47:08 +02004560 grp->nodetype = LYS_GROUPING;
4561 grp->prev = (struct lys_node *)grp;
4562 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004563
Michal Vasko71e1aa82015-08-12 12:17:51 +02004564 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004565 goto error;
4566 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004567
Radek Krejcia9544502015-08-14 08:24:29 +02004568 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4569
Radek Krejciadb30652016-07-11 15:27:07 +02004570 /* insert the node into the schema tree */
4571 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4572 goto error;
4573 }
4574
Radek Krejci1d82ef62015-08-07 14:44:40 +02004575 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004576 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4577 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004578 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004579 continue;
4580 }
4581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 /* data statements */
4583 if (!strcmp(sub->name, "container") ||
4584 !strcmp(sub->name, "leaf-list") ||
4585 !strcmp(sub->name, "leaf") ||
4586 !strcmp(sub->name, "list") ||
4587 !strcmp(sub->name, "choice") ||
4588 !strcmp(sub->name, "uses") ||
4589 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004590 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02004591 !strcmp(sub->name, "action") ||
4592 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004593 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004594 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 /* array counters */
4597 } else if (!strcmp(sub->name, "typedef")) {
4598 c_tpdf++;
4599 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004600 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 goto error;
4602 }
4603 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4606 if (c_tpdf) {
4607 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004608 if (!grp->tpdf) {
4609 LOGMEM;
4610 goto error;
4611 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004613 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004614 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4615 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004616 if (r) {
4617 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004622 if (!root.child) {
4623 LOGWRN("Grouping \"%s\" without children.", retval->name);
4624 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 LY_TREE_FOR_SAFE(root.child, next, sub) {
4626 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004631 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004635 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004637 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004641 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4642 } else if (!strcmp(sub->name, "anydata")) {
4643 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004644 } else if (!strcmp(sub->name, "action")) {
4645 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02004646 } else if (!strcmp(sub->name, "notification")) {
4647 node = read_yin_notif(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004649 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 goto error;
4651 }
Radek Krejci73adb602015-07-02 18:07:40 +02004652
Michal Vasko345da0a2015-12-02 10:35:55 +01004653 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004657
4658error:
4659
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004660 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004662 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004666}
4667
Michal Vasko0d343d12015-08-24 14:57:36 +02004668/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004669static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004670read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4671 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004672{
Radek Krejcie0674f82015-06-15 13:58:51 +02004673 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004674 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004675 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004676 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004677 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004678 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004679
Radek Krejcie0674f82015-06-15 13:58:51 +02004680 /* init */
4681 memset(&root, 0, sizeof root);
4682
Michal Vasko38d01f72015-06-15 09:41:06 +02004683 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004684 if (!inout) {
4685 LOGMEM;
4686 return NULL;
4687 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004688 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004689
4690 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004691 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004692 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004693 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004694 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004695 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004696 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004697 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004698 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004699 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004700 }
4701
Radek Krejci76512572015-08-04 09:47:08 +02004702 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004703
Radek Krejci6a113852015-07-03 16:04:20 +02004704 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004705 goto error;
4706 }
4707
Radek Krejcia9544502015-08-14 08:24:29 +02004708 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4709
Radek Krejciadb30652016-07-11 15:27:07 +02004710 /* insert the node into the schema tree */
4711 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4712 goto error;
4713 }
4714
Michal Vasko38d01f72015-06-15 09:41:06 +02004715 /* data statements */
4716 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004717 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4718 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004719 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004720 continue;
4721 }
4722
Michal Vasko38d01f72015-06-15 09:41:06 +02004723 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 !strcmp(sub->name, "leaf-list") ||
4725 !strcmp(sub->name, "leaf") ||
4726 !strcmp(sub->name, "list") ||
4727 !strcmp(sub->name, "choice") ||
4728 !strcmp(sub->name, "uses") ||
4729 !strcmp(sub->name, "grouping") ||
4730 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004731 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004732 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004735 } else if (!strcmp(sub->name, "typedef")) {
4736 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004737
Radek Krejci1a31efe2016-07-29 11:04:16 +02004738 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004739 c_must++;
4740
Michal Vasko38d01f72015-06-15 09:41:06 +02004741 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004742 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004743 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004744 }
4745 }
4746
4747 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4748 if (c_tpdf) {
4749 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004750 if (!inout->tpdf) {
4751 LOGMEM;
4752 goto error;
4753 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004754 }
Radek Krejci19332802016-07-29 10:39:46 +02004755 if (c_must) {
4756 inout->must = calloc(c_must, sizeof *inout->must);
4757 if (!inout->must) {
4758 LOGMEM;
4759 goto error;
4760 }
4761 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004762
Radek Krejci73adb602015-07-02 18:07:40 +02004763 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004764 if (!strcmp(sub->name, "must")) {
4765 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4766 inout->must_size++;
4767 if (r) {
4768 goto error;
4769 }
4770 } else { /* typedef */
4771 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4772 inout->tpdf_size++;
4773 if (r) {
4774 goto error;
4775 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004776 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004777 }
4778
4779 /* last part - process data nodes */
4780 LY_TREE_FOR_SAFE(root.child, next, sub) {
4781 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004782 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004783 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004784 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004785 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004786 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004787 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004788 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004789 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004790 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004791 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004792 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004793 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004794 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004795 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004796 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4797 } else if (!strcmp(sub->name, "anydata")) {
4798 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004799 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004800 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004801 goto error;
4802 }
Radek Krejci73adb602015-07-02 18:07:40 +02004803
Michal Vasko345da0a2015-12-02 10:35:55 +01004804 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004805 }
4806
Michal Vasko508a50d2016-09-07 14:50:33 +02004807 /* check XPath dependencies */
4808 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4809 goto error;
4810 }
4811
Michal Vasko38d01f72015-06-15 09:41:06 +02004812 return retval;
4813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004815
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004816 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004817 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004818 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004819 }
4820
4821 return NULL;
4822}
4823
Michal Vasko0d343d12015-08-24 14:57:36 +02004824/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004825static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004826read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4827 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004828{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004829 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004830 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004831 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004832 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004833 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004834 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004835
Michal Vaskoc6551b32015-06-16 10:51:43 +02004836 memset(&root, 0, sizeof root);
4837
Michal Vasko0ea41032015-06-16 08:53:55 +02004838 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004839 if (!notif) {
4840 LOGMEM;
4841 return NULL;
4842 }
Radek Krejci76512572015-08-04 09:47:08 +02004843 notif->nodetype = LYS_NOTIF;
4844 notif->prev = (struct lys_node *)notif;
4845 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004846
Radek Krejci6a113852015-07-03 16:04:20 +02004847 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004848 goto error;
4849 }
4850
Radek Krejcia9544502015-08-14 08:24:29 +02004851 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4852
Radek Krejciadb30652016-07-11 15:27:07 +02004853 /* insert the node into the schema tree */
4854 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4855 goto error;
4856 }
4857
Michal Vasko0ea41032015-06-16 08:53:55 +02004858 /* process rpc's specific children */
4859 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004860 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4861 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004862 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004863 continue;
4864 }
4865
Michal Vasko0ea41032015-06-16 08:53:55 +02004866 /* data statements */
4867 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 !strcmp(sub->name, "leaf-list") ||
4869 !strcmp(sub->name, "leaf") ||
4870 !strcmp(sub->name, "list") ||
4871 !strcmp(sub->name, "choice") ||
4872 !strcmp(sub->name, "uses") ||
4873 !strcmp(sub->name, "grouping") ||
4874 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004875 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004876 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004879 } else if (!strcmp(sub->name, "typedef")) {
4880 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004881 } else if (!strcmp(sub->name, "if-feature")) {
4882 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004883 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004884 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004885 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004886 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004887 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004888 }
4889 }
4890
4891 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4892 if (c_tpdf) {
4893 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004894 if (!notif->tpdf) {
4895 LOGMEM;
4896 goto error;
4897 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004898 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004899 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004900 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4901 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004902 LOGMEM;
4903 goto error;
4904 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004905 }
Radek Krejci19332802016-07-29 10:39:46 +02004906 if (c_must) {
4907 notif->must = calloc(c_must, sizeof *notif->must);
4908 if (!notif->must) {
4909 LOGMEM;
4910 goto error;
4911 }
4912 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004913
Radek Krejci73adb602015-07-02 18:07:40 +02004914 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004915 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004916 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4917 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004918 if (r) {
4919 goto error;
4920 }
Radek Krejci96299152016-06-22 10:17:50 +02004921 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004922 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4923 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004924 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004925 goto error;
4926 }
Radek Krejci19332802016-07-29 10:39:46 +02004927 } else if (!strcmp(sub->name, "must")) {
4928 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4929 notif->must_size++;
4930 if (r) {
4931 goto error;
4932 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004933 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004934 }
4935
4936 /* last part - process data nodes */
4937 LY_TREE_FOR_SAFE(root.child, next, sub) {
4938 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004939 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004940 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004941 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004942 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004943 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004944 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004945 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004946 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004947 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004948 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004949 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004950 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004951 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004952 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004953 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4954 } else if (!strcmp(sub->name, "anydata")) {
4955 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004956 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004957 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004958 goto error;
4959 }
Radek Krejci73adb602015-07-02 18:07:40 +02004960
Michal Vasko345da0a2015-12-02 10:35:55 +01004961 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004962 }
4963
Michal Vasko508a50d2016-09-07 14:50:33 +02004964 /* check XPath dependencies */
4965 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4966 goto error;
4967 }
4968
Michal Vasko0ea41032015-06-16 08:53:55 +02004969 return retval;
4970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004972
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004973 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004974 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004975 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004976 }
4977
4978 return NULL;
4979}
4980
Michal Vasko0d343d12015-08-24 14:57:36 +02004981/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004982static struct lys_node *
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004983read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4984 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004985{
Radek Krejcie0674f82015-06-15 13:58:51 +02004986 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004987 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004988 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004989 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004990 int r;
Pavol Vican3cb70c72016-09-05 11:32:52 +02004991 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004992
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004993 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02004994 if (module->version < 2) {
Michal Vaskobb174852016-07-25 11:00:21 +02004995 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
4996 return NULL;
4997 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004998 for (node = parent; node; node = lys_parent(node)) {
4999 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
5000 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
5001 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
5002 return NULL;
5003 }
5004 }
5005 }
5006
Radek Krejcie0674f82015-06-15 13:58:51 +02005007 /* init */
5008 memset(&root, 0, sizeof root);
5009
Michal Vasko38d01f72015-06-15 09:41:06 +02005010 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005011 if (!rpc) {
5012 LOGMEM;
5013 return NULL;
5014 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005015 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005016 rpc->prev = (struct lys_node *)rpc;
5017 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005018
Radek Krejci6a113852015-07-03 16:04:20 +02005019 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005020 goto error;
5021 }
5022
Radek Krejcia9544502015-08-14 08:24:29 +02005023 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5024
Radek Krejciadb30652016-07-11 15:27:07 +02005025 /* insert the node into the schema tree */
5026 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5027 goto error;
5028 }
5029
Michal Vasko38d01f72015-06-15 09:41:06 +02005030 /* process rpc's specific children */
5031 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005032 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5033 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005034 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005035 continue;
5036 }
5037
Michal Vasko38d01f72015-06-15 09:41:06 +02005038 if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005039 if (c_input) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005040 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005041 goto error;
5042 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005043 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005044 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005045 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005046 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005047 if (c_output) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005048 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005049 goto error;
5050 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005051 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005052 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005053 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005056 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005057 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005058 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005060 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005061 } else if (!strcmp(sub->name, "typedef")) {
5062 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005063 } else if (!strcmp(sub->name, "if-feature")) {
5064 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005065 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005066 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005067 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005068 }
5069 }
5070
5071 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5072 if (c_tpdf) {
5073 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005074 if (!rpc->tpdf) {
5075 LOGMEM;
5076 goto error;
5077 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005078 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005079 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005080 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5081 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005082 LOGMEM;
5083 goto error;
5084 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005085 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005086
Radek Krejci73adb602015-07-02 18:07:40 +02005087 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005088 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005089 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5090 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005091 if (r) {
5092 goto error;
5093 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005094 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005095 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
5096 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005097 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005098 goto error;
5099 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005100 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005101 }
5102
5103 /* last part - process data nodes */
5104 LY_TREE_FOR_SAFE(root.child, next, sub) {
5105 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005106 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005107 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005108 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005109 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005110 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005111 goto error;
5112 }
Radek Krejci73adb602015-07-02 18:07:40 +02005113
Michal Vasko345da0a2015-12-02 10:35:55 +01005114 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005115 }
5116
Michal Vasko38d01f72015-06-15 09:41:06 +02005117 return retval;
5118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005119error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005120
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005121 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005122 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005123 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005124 }
5125
5126 return NULL;
5127}
5128
Michal Vasko0d343d12015-08-24 14:57:36 +02005129/* logs directly
5130 *
Radek Krejci74705112015-06-05 10:25:44 +02005131 * resolve - referenced grouping should be bounded to the namespace (resolved)
5132 * only when uses does not appear in grouping. In a case of grouping's uses,
5133 * we just get information but we do not apply augment or refine to it.
5134 */
Radek Krejci76512572015-08-04 09:47:08 +02005135static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005136read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02005137{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005139 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005140 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005141 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005142 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005143 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005145 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005146 if (!uses) {
5147 LOGMEM;
5148 return NULL;
5149 }
Radek Krejci76512572015-08-04 09:47:08 +02005150 uses->nodetype = LYS_USES;
5151 uses->prev = (struct lys_node *)uses;
5152 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005153
Radek Krejcia9544502015-08-14 08:24:29 +02005154 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005155 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005156
Michal Vaskoe0c59842015-09-24 13:52:20 +02005157 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02005158 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005159 goto error;
5160 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005161
Radek Krejcia9544502015-08-14 08:24:29 +02005162 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5163
Radek Krejciadb30652016-07-11 15:27:07 +02005164 /* insert the node into the schema tree */
5165 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5166 goto error;
5167 }
5168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005170 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005171 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5172 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005173 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005174 continue;
5175 }
5176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 if (!strcmp(sub->name, "refine")) {
5178 c_ref++;
5179 } else if (!strcmp(sub->name, "augment")) {
5180 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005181 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005182 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005183 } else if (!strcmp(sub->name, "when")) {
5184 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005185 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005186 goto error;
5187 }
5188
5189 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005190 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005191 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005192 goto error;
5193 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005194 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005195 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005196 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005198 }
5199 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005201 /* process properties with cardinality 0..n */
5202 if (c_ref) {
5203 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005204 if (!uses->refine) {
5205 LOGMEM;
5206 goto error;
5207 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 }
5209 if (c_aug) {
5210 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005211 if (!uses->augment) {
5212 LOGMEM;
5213 goto error;
5214 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005215 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005216 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005217 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5218 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005219 LOGMEM;
5220 goto error;
5221 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005222 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005223
Radek Krejcia9544502015-08-14 08:24:29 +02005224 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005226 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005227 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005228 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005229 goto error;
5230 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005231 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005232 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5233 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005234 if (r) {
5235 goto error;
5236 }
5237 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005238 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
5239 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005240 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005241 goto error;
5242 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243 }
5244 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005245
Radek Krejci48464ed2016-03-17 15:44:09 +01005246 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005247 goto error;
5248 }
Radek Krejci74705112015-06-05 10:25:44 +02005249
Michal Vasko508a50d2016-09-07 14:50:33 +02005250 /* check XPath dependencies */
5251 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5252 goto error;
5253 }
5254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005255 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005256
5257error:
5258
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005259 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005262}
5263
Michal Vasko0d343d12015-08-24 14:57:36 +02005264/* logs directly
5265 *
5266 * common code for yin_read_module() and yin_read_submodule()
5267 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268static int
Radek Krejcic071c542016-01-27 14:57:51 +01005269read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5270 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005271{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005273 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005274 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005275 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005276 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005278 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005279 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005280 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005281 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02005282 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 +02005283
Radek Krejcic071c542016-01-27 14:57:51 +01005284 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005285 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005287 /* init */
5288 memset(&root, 0, sizeof root);
5289 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005290 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02005291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 /*
5293 * in the first run, we process elements with cardinality of 1 or 0..1 and
5294 * count elements with cardinality 0..n. Data elements (choices, containers,
5295 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5296 * need have all top-level and groupings already prepared at that time. In
5297 * the middle loop, we process other elements with carinality of 0..n since
5298 * we need to allocate arrays to store them.
5299 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005300 LY_TREE_FOR_SAFE(yin->child, next, child) {
5301 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005302 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005303 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005304 continue;
5305 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005306
Radek Krejcic071c542016-01-27 14:57:51 +01005307 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005309 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005310 goto error;
5311 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005312 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005314 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005315 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005317 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 goto error;
5319 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005320 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005321 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005322 goto error;
5323 }
5324 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005325 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005326 } else if (submodule && !strcmp(child->name, "belongs-to")) {
5327 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005328 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005329 goto error;
5330 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005331 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005332 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005333 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 goto error;
5335 }
Radek Krejcif3886932015-06-04 17:36:06 +02005336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005337 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005338 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005339 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005341 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005342 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005343 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005344 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005345 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 goto error;
5347 }
5348 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005349 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 /* check here differs from a generic prefix check, since this prefix
5351 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005352 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005353 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005354 goto error;
5355 }
Radek Krejcic071c542016-01-27 14:57:51 +01005356 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005358 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005359 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005360
5361 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005362 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005363 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005364 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005365 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005366 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005367 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005368 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005370 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005371 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005372 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005373 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005374 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005375 lyxml_unlink_elem(ctx, child, 2);
5376 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005377
Radek Krejci1d82ef62015-08-07 14:44:40 +02005378 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005379 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005380 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02005381 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005383 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005384 } else if (!strcmp(child->name, "container") ||
5385 !strcmp(child->name, "leaf-list") ||
5386 !strcmp(child->name, "leaf") ||
5387 !strcmp(child->name, "list") ||
5388 !strcmp(child->name, "choice") ||
5389 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005390 !strcmp(child->name, "anyxml") ||
5391 !strcmp(child->name, "rpc") ||
5392 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005393 lyxml_unlink_elem(ctx, child, 2);
5394 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005395
Radek Krejci1d82ef62015-08-07 14:44:40 +02005396 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005398 lyxml_unlink_elem(ctx, child, 2);
5399 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005401 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005402 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005403 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005404 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005405 goto error;
5406 }
Radek Krejcic071c542016-01-27 14:57:51 +01005407 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005408 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005409 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005410 goto error;
5411 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005412 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005413 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005414 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005415 goto error;
5416 }
Radek Krejcic071c542016-01-27 14:57:51 +01005417 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005418 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005419 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005420 goto error;
5421 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005422 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005423 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005424 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 goto error;
5426 }
Radek Krejcic071c542016-01-27 14:57:51 +01005427 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005428 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005429 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005430 goto error;
5431 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005432 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005433 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005435 goto error;
5436 }
Radek Krejcic071c542016-01-27 14:57:51 +01005437 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005438 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005439 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005440 goto error;
5441 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005442 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005443 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005444 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005445 goto error;
5446 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005447 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005448 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005449 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005450 goto error;
5451 }
Radek Krejcic071c542016-01-27 14:57:51 +01005452 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005453 if (!strcmp(value, "1")) {
5454 if (submodule) {
5455 if (module->version > 1) {
5456 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5457 goto error;
5458 }
5459 } else {
5460 module->version = 1;
5461 }
5462 } else {
5463 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005464 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005465 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5466 goto error;
5467 }
5468 } else {
5469 module->version = 2;
5470 }
5471 }
5472
Michal Vasko345da0a2015-12-02 10:35:55 +01005473 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005474
Radek Krejci1d82ef62015-08-07 14:44:40 +02005475 } else if (!strcmp(child->name, "extension")) {
5476 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005477
Radek Krejci3d468122015-10-02 13:36:12 +02005478 /* we have the following supported (hardcoded) extensions: */
5479 /* ietf-netconf's get-filter-element-attributes */
5480 if (!strcmp(module->ns, LY_NSNC) &&
5481 !strcmp(value, "get-filter-element-attributes")) {
5482 LOGDBG("NETCONF filter extension found");
5483 /* NACM's default-deny-write and default-deny-all */
5484 } else if (!strcmp(module->ns, LY_NSNACM) &&
5485 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5486 LOGDBG("NACM extension found");
5487 /* other extensions are not supported, so inform about such an extension */
5488 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005489 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005490 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005491 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005492 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005493 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005494 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005495 }
5496 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005497
Radek Krejcic071c542016-01-27 14:57:51 +01005498 /* check for mandatory statements */
5499 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005500 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005501 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005502 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005503 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005504 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005505 goto error;
5506 }
5507 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005508 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005509 goto error;
5510 }
5511 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005513 /* allocate arrays for elements with cardinality of 0..n */
5514 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005515 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5516 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005517 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005518 LOGMEM;
5519 goto error;
5520 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005521 /* set stop block for possible realloc */
5522 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005523 }
5524 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005525 trg->rev = calloc(c_rev, sizeof *trg->rev);
5526 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005527 LOGMEM;
5528 goto error;
5529 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005530 }
5531 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005532 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5533 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005534 LOGMEM;
5535 goto error;
5536 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005537 }
5538 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005539 trg->ident = calloc(c_ident, sizeof *trg->ident);
5540 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005541 LOGMEM;
5542 goto error;
5543 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005544 }
5545 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005546 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5547 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005548 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005549 LOGMEM;
5550 goto error;
5551 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005552 /* set stop block for possible realloc */
5553 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005554 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005555 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005556 trg->augment = calloc(c_aug, sizeof *trg->augment);
5557 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005558 LOGMEM;
5559 goto error;
5560 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005561 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005562 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005563 trg->features = calloc(c_ftrs, sizeof *trg->features);
5564 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005565 LOGMEM;
5566 goto error;
5567 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005568 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005569 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005570 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5571 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005572 LOGMEM;
5573 goto error;
5574 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005575 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005576
Michal Vasko2f7925f2015-10-21 15:06:56 +02005577 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5578 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005579 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005580 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5581 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005582 if (r) {
5583 goto error;
5584 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005585
Radek Krejci1d82ef62015-08-07 14:44:40 +02005586 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005587 memset(&inc, 0, sizeof inc);
5588 /* 1) pass module, not trg, since we want to pass the main module
5589 * 2) we cannot pass directly the structure in the array since
5590 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01005591 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005592 if (!r) {
5593 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02005594 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
5595 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005596 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005597 goto error;
5598 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005599
Radek Krejci1d82ef62015-08-07 14:44:40 +02005600 } else if (!strcmp(child->name, "revision")) {
5601 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005602 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005603 goto error;
5604 }
Radek Krejcic071c542016-01-27 14:57:51 +01005605 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005606 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005607 for (i = 0; i < trg->rev_size; i++) {
5608 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005609 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5610 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005611 }
5612 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005613
Radek Krejci1d82ef62015-08-07 14:44:40 +02005614 LY_TREE_FOR(child->child, child2) {
5615 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005616 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005617 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005618 goto error;
5619 }
Radek Krejcic071c542016-01-27 14:57:51 +01005620 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5621 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005622 goto error;
5623 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005624 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005625 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005626 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005627 goto error;
5628 }
Radek Krejcic071c542016-01-27 14:57:51 +01005629 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5630 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005631 goto error;
5632 }
5633 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005634 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005635 goto error;
5636 }
5637 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005639 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005640 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005641 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005642 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005643 if (!value) {
5644 LOGMEM;
5645 goto error;
5646 }
Radek Krejcic071c542016-01-27 14:57:51 +01005647 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5648 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005649 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005650
Radek Krejci749190d2016-02-18 16:26:25 +01005651 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005652 value = trg->rev[0].dsc;
5653 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5654 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005655 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005656
Radek Krejci749190d2016-02-18 16:26:25 +01005657 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005658 value = trg->rev[0].ref;
5659 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5660 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005661 }
5662 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005663
Radek Krejcic071c542016-01-27 14:57:51 +01005664 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005665
Radek Krejci1d82ef62015-08-07 14:44:40 +02005666 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005667 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5668 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 if (r) {
5670 goto error;
5671 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005672
Radek Krejci1d82ef62015-08-07 14:44:40 +02005673 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005674 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5675 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005676 if (r) {
5677 goto error;
5678 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005679
Radek Krejci1d82ef62015-08-07 14:44:40 +02005680 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005681 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5682 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005683 if (r) {
5684 goto error;
5685 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005686
Radek Krejci1d82ef62015-08-07 14:44:40 +02005687 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005688 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5689 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005690 if (r) {
5691 goto error;
5692 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005693 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005694 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005695
Radek Krejcib8f98c12016-06-24 10:30:46 +02005696 if (!submodule) {
5697 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005698 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005699 if (module->inc_size) {
5700 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5701 if (!module->inc) {
5702 LOGMEM;
5703 goto error;
5704 }
5705 }
5706 if (module->imp_size) {
5707 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5708 if (!module->imp) {
5709 LOGMEM;
5710 goto error;
5711 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005712 }
5713 }
Radek Krejcic071c542016-01-27 14:57:51 +01005714
Radek Krejcif5be10f2015-06-16 13:29:36 +02005715 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005716 * refer to them. Submodule's data nodes are stored in the
5717 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005718 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005719 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005720 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005721 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005722 goto error;
5723 }
Radek Krejci74705112015-06-05 10:25:44 +02005724
Michal Vasko345da0a2015-12-02 10:35:55 +01005725 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005726 }
Radek Krejci74705112015-06-05 10:25:44 +02005727
Radek Krejcif5be10f2015-06-16 13:29:36 +02005728 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005729 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005730
Radek Krejci1d82ef62015-08-07 14:44:40 +02005731 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005732 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005733 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005734 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005735 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005736 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005737 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005738 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005739 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005740 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005741 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005742 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005743 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02005744 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
5745 } else if (!strcmp(child->name, "anydata")) {
5746 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005747 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005748 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005749 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005750 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005751 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005752 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005753 goto error;
5754 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005755
Michal Vasko345da0a2015-12-02 10:35:55 +01005756 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005757 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005758
Michal Vasko2f7925f2015-10-21 15:06:56 +02005759 /* ... and finally augments (last, so we can augment our data, for instance) */
5760 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005761 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5762 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005763
Michal Vasko2f7925f2015-10-21 15:06:56 +02005764 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005765 goto error;
5766 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005767 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005768 }
5769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005770 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005771
5772error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005773 /* cleanup */
5774 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005775 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005776 }
5777 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005778 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005779 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005780 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005781 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005782 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005784 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005785}
5786
Michal Vasko0d343d12015-08-24 14:57:36 +02005787/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005788struct lys_submodule *
5789yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005790{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005791 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005792 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005793 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005794
Michal Vasko5a721fd2016-02-16 12:16:48 +01005795 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005796
Radek Krejci722b0072016-02-01 17:09:45 +01005797 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005798 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005799 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005800 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005802 /* check root element */
5803 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005804 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005805 goto error;
5806 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005808 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005809 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005810 goto error;
5811 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005812
Michal Vasko5a721fd2016-02-16 12:16:48 +01005813 submodule = calloc(1, sizeof *submodule);
5814 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005815 LOGMEM;
5816 goto error;
5817 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005818
Michal Vasko5a721fd2016-02-16 12:16:48 +01005819 submodule->ctx = module->ctx;
5820 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5821 submodule->type = 1;
5822 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005823
Michal Vasko5a721fd2016-02-16 12:16:48 +01005824 LOGVRB("Reading submodule \"%s\".", submodule->name);
5825 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005826 goto error;
5827 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005829 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005830 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005831
Michal Vasko5a721fd2016-02-16 12:16:48 +01005832 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005833 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005834
5835error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005836 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005837 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005838 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005839
Michal Vasko5a721fd2016-02-16 12:16:48 +01005840 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005841 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005842 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005843 }
5844
Michal Vasko5a721fd2016-02-16 12:16:48 +01005845 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005846
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005847 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5848 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005849 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005850 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005851}
5852
Michal Vasko0d343d12015-08-24 14:57:36 +02005853/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005854struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005855yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005856{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005857 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005858 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005859 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005860 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005861
Radek Krejcic071c542016-01-27 14:57:51 +01005862 unres = calloc(1, sizeof *unres);
5863 if (!unres) {
5864 LOGMEM;
5865 return NULL;
5866 }
5867
Radek Krejci722b0072016-02-01 17:09:45 +01005868 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005869 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005870 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005871 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005872
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005873 /* check root element */
5874 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005875 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005876 goto error;
5877 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005879 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005880 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005881 goto error;
5882 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005884 module = calloc(1, sizeof *module);
5885 if (!module) {
5886 LOGMEM;
5887 goto error;
5888 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005890 module->ctx = ctx;
5891 module->name = lydict_insert(ctx, value, strlen(value));
5892 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005893 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005894
Michal Vasko9f258e42016-02-11 11:36:27 +01005895 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005896 if (read_sub_module(module, NULL, yin, unres)) {
5897 goto error;
5898 }
5899
5900 /* resolve rest of unres items */
5901 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005902 goto error;
5903 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005904
Radek Krejciff4874d2016-03-07 12:30:50 +01005905 if (revision) {
5906 /* check revision of the parsed model */
5907 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005908 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5909 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005910 goto error;
5911 }
5912 }
5913
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005914 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005915 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005916 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005917
Radek Krejci27fe55e2016-09-13 17:13:35 +02005918 if (module->deviation_size && !module->implemented) {
5919 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
5920 /* deviations always causes target to be made implemented,
5921 * but augents and leafrefs not, so we have to apply them now */
5922 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02005923 goto error;
5924 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005925 }
5926
Michal Vasko345da0a2015-12-02 10:35:55 +01005927 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005928 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005929 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005930 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005931
5932error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005933 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005934 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005935 unres_schema_free(module, &unres);
5936
5937 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005938 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005939 return NULL;
5940 }
5941
5942 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005943
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005944 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005945 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005946 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005947}