blob: 230320881cf6fd09d013c53c288720ab5926a484 [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 Vaskoc3d9f8c2015-07-31 14:37:24 +02002478 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002479 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002480 goto error;
2481 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002482
Radek Krejci1d82ef62015-08-07 14:44:40 +02002483 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002484 goto error;
2485 }
2486
Radek Krejci1d82ef62015-08-07 14:44:40 +02002487 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002488 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002489 }
2490
2491 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002492 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2493 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002494 LOGMEM;
2495 goto error;
2496 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002497 }
2498
2499 LY_TREE_FOR_SAFE(yin->child, next, child) {
2500 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002501 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2502 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002503 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002504 goto error;
2505 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002506 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002507 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002508 }
2509
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002510 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002511 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002512 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002513 * when the uses does and cannot be resolved now for sure
2514 * (the grouping was not yet copied into uses).
2515 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002516 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002517 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002518 goto error;
2519 }
Michal Vasko49291b32015-08-06 09:49:41 +02002520 }
Radek Krejci106efc02015-06-10 14:36:27 +02002521
Michal Vasko508a50d2016-09-07 14:50:33 +02002522 /* check XPath dependencies */
2523 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2524 goto error;
2525 }
2526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002528
2529error:
2530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002532}
2533
Michal Vasko0d343d12015-08-24 14:57:36 +02002534/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002536fill_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 +02002537{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002538 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539 struct lyxml_elem *sub, *next;
2540 const char *value;
2541 char *endptr;
2542 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci200bf712016-08-16 17:11:04 +02002543 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002544 int r;
2545 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002546
Radek Krejci363bd4a2016-07-29 14:30:20 +02002547 assert(uses);
2548 module = uses->module; /* shorthand */
2549
Radek Krejci76512572015-08-04 09:47:08 +02002550 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002551 goto error;
2552 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002553
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002554 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002555 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002556 if (!rfn->target_name) {
2557 goto error;
2558 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002561 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2562 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002563 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002564 continue;
2565 }
2566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 /* limited applicability */
2568 if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002569 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 /* check possibility of statements combination */
2572 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002573 if (c_dflt) {
2574 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002575 if (module->version < 2) {
2576 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2577 goto error;
2578 }
Radek Krejci200bf712016-08-16 17:11:04 +02002579 rfn->target_type &= LYS_LEAFLIST;
2580 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002581 if (module->version < 2) {
2582 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2583 } else {
2584 /* YANG 1.1 */
2585 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2586 }
Radek Krejci200bf712016-08-16 17:11:04 +02002587 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002588 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002589 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2590 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002591 goto error;
2592 }
2593 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002594 if (module->version < 2) {
2595 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2596 } else {
2597 /* YANG 1.1 */
2598 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2599 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002601
Radek Krejci200bf712016-08-16 17:11:04 +02002602 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002603 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 } else if (!strcmp(sub->name, "mandatory")) {
2605 /* leaf, choice or anyxml */
2606 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002607 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002608 goto error;
2609 }
2610 /* just checking the flags in leaf is not sufficient, we would allow
2611 * multiple mandatory statements with the "false" value
2612 */
2613 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002615 /* check possibility of statements combination */
2616 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002617 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002618 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002619 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2620 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002621 goto error;
2622 }
2623 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002624 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 GETVAL(value, sub, "value");
2628 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002629 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002630 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002631 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002632 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002633 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 goto error;
2635 }
2636 } else if (!strcmp(sub->name, "min-elements")) {
2637 /* list or leaf-list */
2638 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002639 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640 goto error;
2641 }
2642 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002644 /* check possibility of statements combination */
2645 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002646 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002648 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2649 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002650 goto error;
2651 }
2652 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002653 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002654 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002656 GETVAL(value, sub, "value");
2657 while (isspace(value[0])) {
2658 value++;
2659 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002661 /* convert it to uint32_t */
2662 errno = 0;
2663 endptr = NULL;
2664 val = strtoul(value, &endptr, 10);
2665 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002666 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667 goto error;
2668 }
2669 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002670 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002671 } else if (!strcmp(sub->name, "max-elements")) {
2672 /* list or leaf-list */
2673 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002674 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002675 goto error;
2676 }
2677 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 /* check possibility of statements combination */
2680 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002681 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002682 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002683 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2684 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002685 goto error;
2686 }
2687 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002688 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002689 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 GETVAL(value, sub, "value");
2692 while (isspace(value[0])) {
2693 value++;
2694 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002695
Radek Krejci0d7b2472016-02-12 11:11:03 +01002696 if (!strcmp(value, "unbounded")) {
2697 rfn->mod.list.max = 0;
2698 } else {
2699 /* convert it to uint32_t */
2700 errno = 0;
2701 endptr = NULL;
2702 val = strtoul(value, &endptr, 10);
2703 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002704 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002705 goto error;
2706 }
2707 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002708 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002709 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 } else if (!strcmp(sub->name, "presence")) {
2711 /* container */
2712 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002713 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 goto error;
2715 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002717 /* check possibility of statements combination */
2718 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002719 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002721 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2722 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 goto error;
2724 }
2725 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002726 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002729 GETVAL(value, sub, "value");
2730 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2731 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002732 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 /* check possibility of statements combination */
2734 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002735 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002737 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2738 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 goto error;
2740 }
2741 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002742 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002746 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002747
Radek Krejci363bd4a2016-07-29 14:30:20 +02002748 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2749 /* leaf, leaf-list, list, container or anyxml */
2750 /* check possibility of statements combination */
2751 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002752 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002753 if (!rfn->target_type) {
2754 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2755 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2756 goto error;
2757 }
2758 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002759 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002760 }
2761
2762 c_ftrs++;
2763 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002765 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 goto error;
2767 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002768
Michal Vasko345da0a2015-12-02 10:35:55 +01002769 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002770 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 /* process nodes with cardinality of 0..n */
2773 if (c_must) {
2774 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002775 if (!rfn->must) {
2776 LOGMEM;
2777 goto error;
2778 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002780 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002781 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002782 if (!rfn->iffeature) {
2783 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002784 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 }
Radek Krejci200bf712016-08-16 17:11:04 +02002787 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002788 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002789 if (!rfn->dflt) {
2790 LOGMEM;
2791 goto error;
2792 }
2793 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002794
Radek Krejci363bd4a2016-07-29 14:30:20 +02002795 LY_TREE_FOR(yin->child, sub) {
2796 if (!strcmp(sub->name, "if-feature")) {
2797 r = fill_yin_iffeature(uses, sub, &rfn->iffeature[rfn->iffeature_size], unres);
2798 rfn->iffeature_size++;
2799 if (r) {
2800 goto error;
2801 }
Radek Krejci200bf712016-08-16 17:11:04 +02002802 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002803 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2804 rfn->must_size++;
2805 if (r) {
2806 goto error;
2807 }
Radek Krejci200bf712016-08-16 17:11:04 +02002808 } else { /* default */
2809 GETVAL(value, sub, "value");
2810
2811 /* check for duplicity */
2812 for (r = 0; r < rfn->dflt_size; r++) {
2813 if (ly_strequal(rfn->dflt[r], value, 1)) {
2814 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2815 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2816 goto error;
2817 }
2818 }
2819 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02002820 }
2821 }
2822
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002824
2825error:
2826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002827 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002828}
2829
Michal Vasko0d343d12015-08-24 14:57:36 +02002830/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831static int
Radek Krejcib8048692015-08-05 13:36:34 +02002832fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002833{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834 struct lyxml_elem *child;
2835 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002838 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2839 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002840 continue;
2841 }
2842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002843 if (!strcmp(child->name, "prefix")) {
2844 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002845 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002846 goto error;
2847 }
2848 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2849 } else if (!strcmp(child->name, "revision-date")) {
2850 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002851 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2852 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 }
2854 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002855 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 goto error;
2857 }
2858 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002859 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002860 if (imp->dsc) {
2861 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2862 goto error;
2863 }
2864 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2865 if (!imp->dsc) {
2866 goto error;
2867 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002868 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002869 if (imp->ref) {
2870 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2871 goto error;
2872 }
2873 imp->ref = read_yin_subnode(module->ctx, child, "text");
2874 if (!imp->ref) {
2875 goto error;
2876 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002878 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002879 goto error;
2880 }
2881 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 /* check mandatory information */
2884 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002885 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 goto error;
2887 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002889 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002890
Pavol Vicane994fda2016-03-22 10:47:58 +01002891 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002892
2893error:
2894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002896}
2897
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002898/* logs directly
2899 * returns:
2900 * 0 - inc successfully filled
2901 * -1 - error, inc is cleaned
2902 * 1 - duplication, ignore the inc structure, inc is cleaned
2903 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002904static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002905fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2906 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002907{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908 struct lyxml_elem *child;
2909 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002912 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2913 /* garbage */
2914 continue;
2915 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002916 if (!strcmp(child->name, "revision-date")) {
2917 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002918 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 goto error;
2920 }
2921 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002922 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 goto error;
2924 }
2925 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002926 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002927 if (inc->dsc) {
2928 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2929 goto error;
2930 }
2931 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2932 if (!inc->dsc) {
2933 goto error;
2934 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002935 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002936 if (inc->ref) {
2937 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2938 goto error;
2939 }
2940 inc->ref = read_yin_subnode(module->ctx, child, "text");
2941 if (!inc->ref) {
2942 goto error;
2943 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002945 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 goto error;
2947 }
2948 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002951
Pavol Vican0adf01d2016-03-22 12:29:33 +01002952 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002953
2954error:
2955
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002956 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002957}
2958
Michal Vasko0d343d12015-08-24 14:57:36 +02002959/* logs directly
2960 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002961 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002962 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002963 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002964 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002965static int
Radek Krejcib8048692015-08-05 13:36:34 +02002966read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002967 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002968{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969 const char *value;
2970 struct lyxml_elem *sub, *next;
2971 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002974 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 if (opt & OPT_IDENT) {
2978 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002979 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 goto error;
2981 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002982 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002984
Radek Krejci6764bb32015-07-03 15:16:04 +02002985 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002986 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002987 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002988 }
2989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 /* process local parameters */
2991 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002992 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002993 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002994 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002995 continue;
2996 }
2997 if (strcmp(sub->ns->value, LY_NSYIN)) {
2998 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002999 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003000 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003001 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02003002 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003003 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02003004 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003005 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02003006 goto error;
3007 }
3008 }
3009
3010 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003011 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003012 continue;
3013 }
3014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003015 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003016 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003017 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 goto error;
3019 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003020 node->dsc = read_yin_subnode(ctx, sub, "text");
3021 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003022 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003023 }
3024 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003025 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003026 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 goto error;
3028 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003029 node->ref = read_yin_subnode(ctx, sub, "text");
3030 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003031 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 }
3033 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003034 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003035 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003036 goto error;
3037 }
3038 GETVAL(value, sub, "value");
3039 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003040 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003042 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003044 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003046 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003047 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 }
3049 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003050 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003051 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 goto error;
3053 }
3054 GETVAL(value, sub, "value");
3055 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003056 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003058 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003060 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003061 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02003063 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003065 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 continue;
3067 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003068 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003070
Radek Krejci1d82ef62015-08-07 14:44:40 +02003071 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02003073 if (parent && (parent->flags & LYS_CONFIG_R)) {
3074 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 } else {
3076 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003077 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 }
3079 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003082
3083error:
3084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003086}
3087
Michal Vasko0d343d12015-08-24 14:57:36 +02003088/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003089static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003090read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003091{
Radek Krejci76512572015-08-04 09:47:08 +02003092 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003093 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003094 const char *value;
3095
3096 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003097 if (!retval) {
3098 LOGMEM;
3099 return NULL;
3100 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003101
3102 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003103 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003104 if (!retval->cond) {
3105 goto error;
3106 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003107
Radek Krejci73adb602015-07-02 18:07:40 +02003108 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003109 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3110 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003111 continue;
3112 }
3113
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003114 if (!strcmp(child->name, "description")) {
3115 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003116 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003117 goto error;
3118 }
3119 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3120 if (!retval->dsc) {
3121 goto error;
3122 }
3123 } else if (!strcmp(child->name, "reference")) {
3124 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003125 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003126 goto error;
3127 }
3128 retval->ref = read_yin_subnode(module->ctx, child, "text");
3129 if (!retval->ref) {
3130 goto error;
3131 }
3132 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003133 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003134 goto error;
3135 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003136 }
3137
3138 return retval;
3139
3140error:
3141
Michal Vasko0308dd62015-10-07 09:14:40 +02003142 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003143 return NULL;
3144}
3145
Michal Vasko0d343d12015-08-24 14:57:36 +02003146/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003147static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003148read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3149 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003150{
Michal Vasko29fc0182015-08-24 15:02:39 +02003151 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003152 struct lys_node_case *cs;
3153 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02003154 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003155
Radek Krejcie867c852015-08-27 09:52:34 +02003156 /* init */
3157 memset(&root, 0, sizeof root);
3158
Radek Krejci1d82ef62015-08-07 14:44:40 +02003159 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003160 if (!cs) {
3161 LOGMEM;
3162 return NULL;
3163 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003164 cs->nodetype = LYS_CASE;
3165 cs->prev = (struct lys_node *)cs;
3166 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003167
Radek Krejci6a113852015-07-03 16:04:20 +02003168 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 goto error;
3170 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003171
Radek Krejcia9544502015-08-14 08:24:29 +02003172 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3173
Michal Vasko3a0043f2015-08-12 12:11:30 +02003174 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003175 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003176 goto error;
3177 }
3178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 /* process choice's specific children */
3180 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003181 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3182 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003183 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003184 continue;
3185 }
3186
Michal Vasko29fc0182015-08-24 15:02:39 +02003187 if (!strcmp(sub->name, "container") ||
3188 !strcmp(sub->name, "leaf-list") ||
3189 !strcmp(sub->name, "leaf") ||
3190 !strcmp(sub->name, "list") ||
3191 !strcmp(sub->name, "uses") ||
3192 !strcmp(sub->name, "choice") ||
3193 !strcmp(sub->name, "anyxml")) {
3194
Michal Vaskof3930de2015-10-22 12:03:59 +02003195 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003196 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003197 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003198 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01003199 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02003200 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003201 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003202 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003203 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003204 goto error;
3205 }
3206
Radek Krejci1d82ef62015-08-07 14:44:40 +02003207 cs->when = read_yin_when(module, sub);
3208 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003209 goto error;
3210 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003211
Michal Vasko345da0a2015-12-02 10:35:55 +01003212 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003214 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003217 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003218
Radek Krejci3cf9e222015-06-18 11:37:50 +02003219 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003220 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3221 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003222 LOGMEM;
3223 goto error;
3224 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003225 }
Radek Krejci73adb602015-07-02 18:07:40 +02003226 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003227 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
3228 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003229 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003230 goto error;
3231 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 }
Radek Krejcib388c152015-06-04 17:03:03 +02003233
Michal Vasko29fc0182015-08-24 15:02:39 +02003234 /* last part - process data nodes */
3235 LY_TREE_FOR_SAFE(root.child, next, sub) {
3236 if (!strcmp(sub->name, "container")) {
3237 node = read_yin_container(module, retval, sub, resolve, unres);
3238 } else if (!strcmp(sub->name, "leaf-list")) {
3239 node = read_yin_leaflist(module, retval, sub, resolve, unres);
3240 } else if (!strcmp(sub->name, "leaf")) {
3241 node = read_yin_leaf(module, retval, sub, resolve, unres);
3242 } else if (!strcmp(sub->name, "list")) {
3243 node = read_yin_list(module, retval, sub, resolve, unres);
3244 } else if (!strcmp(sub->name, "choice")) {
3245 node = read_yin_choice(module, retval, sub, resolve, unres);
3246 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003247 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003248 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003249 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
3250 } else if (!strcmp(sub->name, "anydata")) {
3251 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003252 }
3253 if (!node) {
3254 goto error;
3255 }
3256
Michal Vasko345da0a2015-12-02 10:35:55 +01003257 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003258 }
3259
Michal Vasko508a50d2016-09-07 14:50:33 +02003260 /* check XPath dependencies */
3261 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3262 goto error;
3263 }
3264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003266
3267error:
3268
Michal Vasko29fc0182015-08-24 15:02:39 +02003269 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003270 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003271 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003272 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003275}
3276
Michal Vasko0d343d12015-08-24 14:57:36 +02003277/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003278static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02003279read_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 +02003280{
Radek Krejci629cdef2016-06-06 15:06:36 +02003281 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003282 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003283 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003284 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003285 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02003286 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003289 if (!choice) {
3290 LOGMEM;
3291 return NULL;
3292 }
Radek Krejci76512572015-08-04 09:47:08 +02003293 choice->nodetype = LYS_CHOICE;
3294 choice->prev = (struct lys_node *)choice;
3295 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003296
Michal Vaskoe0c59842015-09-24 13:52:20 +02003297 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3298 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 goto error;
3300 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003301
Radek Krejcia9544502015-08-14 08:24:29 +02003302 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3303
Michal Vasko3a0043f2015-08-12 12:11:30 +02003304 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003305 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003306 goto error;
3307 }
3308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 /* process choice's specific children */
3310 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003311 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3312 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003313 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003314 continue;
3315 }
3316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003318 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 goto error;
3320 }
3321 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003322 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 goto error;
3324 }
3325 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003326 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 goto error;
3328 }
3329 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003330 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 goto error;
3332 }
3333 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003334 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 goto error;
3336 }
3337 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003338 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres))) {
3339 goto error;
3340 }
3341 } else if (!strcmp(sub->name, "anydata")) {
3342 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
3344 }
3345 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003346 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003347 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 goto error;
3349 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003350 dflt = sub;
3351 lyxml_unlink_elem(ctx, dflt, 0);
3352
Radek Krejcif9a312c2016-06-06 15:14:30 +02003353 continue;
3354 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 } else if (!strcmp(sub->name, "mandatory")) {
3357 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003358 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 goto error;
3360 }
3361 /* just checking the flags in leaf is not sufficient, we would allow
3362 * multiple mandatory statements with the "false" value
3363 */
3364 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 GETVAL(value, sub, "value");
3367 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003368 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003369 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003370 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003371 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003372 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 goto error;
3374 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003375 } else if (!strcmp(sub->name, "when")) {
3376 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003377 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003378 goto error;
3379 }
3380
3381 choice->when = read_yin_when(module, sub);
3382 if (!choice->when) {
3383 goto error;
3384 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003385 } else if (!strcmp(sub->name, "if-feature")) {
3386 c_ftrs++;
3387
Michal Vasko345da0a2015-12-02 10:35:55 +01003388 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003389 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003390 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
3391 if (!(node = read_yin_choice(module, retval, sub, resolve, unres))) {
3392 goto error;
3393 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003394 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003395 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003397 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003398
Radek Krejci1d82ef62015-08-07 14:44:40 +02003399 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003400 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003402
Radek Krejci3cf9e222015-06-18 11:37:50 +02003403 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003404 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3405 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003406 LOGMEM;
3407 goto error;
3408 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003409 }
3410
Radek Krejci73adb602015-07-02 18:07:40 +02003411 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003412 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
3413 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003414 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003415 goto error;
3416 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003417 }
3418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003420 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003421 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
3422 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 goto error;
3424 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003427 if (dflt) {
3428 GETVAL(value, dflt, "value");
3429 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003430 goto error;
3431 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003432 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003434
Michal Vasko508a50d2016-09-07 14:50:33 +02003435 /* check XPath dependencies */
3436 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3437 goto error;
3438 }
3439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003441
3442error:
3443
Radek Krejci629cdef2016-06-06 15:06:36 +02003444 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003445 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003448}
3449
Michal Vasko0d343d12015-08-24 14:57:36 +02003450/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003451static struct lys_node *
Radek Krejcibf2abff2016-08-23 15:51:52 +02003452read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type, int resolve,
3453 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003454{
Radek Krejci76512572015-08-04 09:47:08 +02003455 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003456 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 struct lyxml_elem *sub, *next;
3458 const char *value;
3459 int r;
3460 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003461 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003464 if (!anyxml) {
3465 LOGMEM;
3466 return NULL;
3467 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003468 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003469 anyxml->prev = (struct lys_node *)anyxml;
3470 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003471
Michal Vaskoe0c59842015-09-24 13:52:20 +02003472 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3473 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 goto error;
3475 }
Radek Krejci863c2852015-06-03 15:47:11 +02003476
Radek Krejcia9544502015-08-14 08:24:29 +02003477 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003478
Radek Krejciadb30652016-07-11 15:27:07 +02003479 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003480 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003481 goto error;
3482 }
3483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003485 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3486 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003487 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003488 continue;
3489 }
3490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 if (!strcmp(sub->name, "mandatory")) {
3492 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003493 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 goto error;
3495 }
3496 /* just checking the flags in leaf is not sufficient, we would allow
3497 * multiple mandatory statements with the "false" value
3498 */
3499 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 GETVAL(value, sub, "value");
3502 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003503 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003504 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003505 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003506 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003507 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 goto error;
3509 }
3510 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003511 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003512 } else if (!strcmp(sub->name, "when")) {
3513 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003514 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003515 goto error;
3516 }
3517
3518 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003519 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003520 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003521 goto error;
3522 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003523 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003524 } else if (!strcmp(sub->name, "must")) {
3525 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003526 } else if (!strcmp(sub->name, "if-feature")) {
3527 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003530 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 }
3533 }
Radek Krejci863c2852015-06-03 15:47:11 +02003534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 /* middle part - process nodes with cardinality of 0..n */
3536 if (c_must) {
3537 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003538 if (!anyxml->must) {
3539 LOGMEM;
3540 goto error;
3541 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003543 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003544 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3545 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003546 LOGMEM;
3547 goto error;
3548 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003549 }
Radek Krejci863c2852015-06-03 15:47:11 +02003550
Radek Krejci73adb602015-07-02 18:07:40 +02003551 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003553 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3554 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 if (r) {
3556 goto error;
3557 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003558 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003559 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3560 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003561 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003562 goto error;
3563 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 }
Radek Krejci863c2852015-06-03 15:47:11 +02003566
Michal Vasko508a50d2016-09-07 14:50:33 +02003567 /* check XPath dependencies */
3568 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3569 goto error;
3570 }
3571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003573
3574error:
3575
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003576 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003579}
3580
Michal Vasko0d343d12015-08-24 14:57:36 +02003581/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003582static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003583read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003584 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003585{
Radek Krejci76512572015-08-04 09:47:08 +02003586 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003587 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 struct lyxml_elem *sub, *next;
3589 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003590 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003591 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003594 if (!leaf) {
3595 LOGMEM;
3596 return NULL;
3597 }
Radek Krejci76512572015-08-04 09:47:08 +02003598 leaf->nodetype = LYS_LEAF;
3599 leaf->prev = (struct lys_node *)leaf;
3600 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003601
Michal Vaskoe0c59842015-09-24 13:52:20 +02003602 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3603 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 goto error;
3605 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003606
Radek Krejcia9544502015-08-14 08:24:29 +02003607 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003608
Radek Krejciadb30652016-07-11 15:27:07 +02003609 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003610 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003611 goto error;
3612 }
3613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003615 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3616 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003617 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003618 continue;
3619 }
3620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003622 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003623 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 goto error;
3625 }
Michal Vasko88c29542015-11-27 14:57:53 +01003626 /* HACK for unres */
3627 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003628 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko3767fb22016-07-21 12:10:57 +02003629 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003630 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 goto error;
3632 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003633 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003634 } else if (!strcmp(sub->name, "default")) {
3635 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003636 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 goto error;
3638 }
3639 GETVAL(value, sub, "value");
3640 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3641 } else if (!strcmp(sub->name, "units")) {
3642 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003643 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003644 goto error;
3645 }
3646 GETVAL(value, sub, "name");
3647 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3648 } else if (!strcmp(sub->name, "mandatory")) {
3649 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003650 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 goto error;
3652 }
3653 /* just checking the flags in leaf is not sufficient, we would allow
3654 * multiple mandatory statements with the "false" value
3655 */
3656 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003658 GETVAL(value, sub, "value");
3659 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003660 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003661 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003662 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003663 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003664 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 goto error;
3666 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003667 } else if (!strcmp(sub->name, "when")) {
3668 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003669 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003670 goto error;
3671 }
3672
3673 leaf->when = read_yin_when(module, sub);
3674 if (!leaf->when) {
3675 goto error;
3676 }
3677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003678 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003679 c_must++;
3680 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003681 } else if (!strcmp(sub->name, "if-feature")) {
3682 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003686 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003689
Michal Vasko88c29542015-11-27 14:57:53 +01003690 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003692
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003694 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003695 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 goto error;
3697 }
Michal Vasko478c4652016-07-21 12:55:01 +02003698 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3699 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3700 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3701 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3702 goto error;
3703 }
3704
3705 /* check default value (if not defined, there still could be some restrictions
3706 * that need to be checked against a default value from a derived type) */
3707 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3708 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 /* middle part - process nodes with cardinality of 0..n */
3712 if (c_must) {
3713 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003714 if (!leaf->must) {
3715 LOGMEM;
3716 goto error;
3717 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003719 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003720 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3721 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003722 LOGMEM;
3723 goto error;
3724 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003725 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003726
Radek Krejci73adb602015-07-02 18:07:40 +02003727 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003729 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3730 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 if (r) {
3732 goto error;
3733 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003734 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003735 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3736 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003737 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003738 goto error;
3739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003741 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003742
Michal Vasko508a50d2016-09-07 14:50:33 +02003743 /* check XPath dependencies */
3744 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3745 goto error;
3746 }
3747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003749
3750error:
3751
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003752 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755}
3756
Michal Vasko0d343d12015-08-24 14:57:36 +02003757/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003758static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003759read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003760 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761{
Radek Krejci76512572015-08-04 09:47:08 +02003762 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003763 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003764 struct lyxml_elem *sub, *next;
3765 const char *value;
3766 char *endptr;
3767 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003768 int r, has_type = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003769 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003773 if (!llist) {
3774 LOGMEM;
3775 return NULL;
3776 }
Radek Krejci76512572015-08-04 09:47:08 +02003777 llist->nodetype = LYS_LEAFLIST;
3778 llist->prev = (struct lys_node *)llist;
3779 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003780
Michal Vaskoe0c59842015-09-24 13:52:20 +02003781 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3782 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 goto error;
3784 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003785
Radek Krejcia9544502015-08-14 08:24:29 +02003786 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003787
Radek Krejciadb30652016-07-11 15:27:07 +02003788 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003789 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003790 goto error;
3791 }
3792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003794 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3795 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003796 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003797 continue;
3798 }
3799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003801 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003802 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 goto error;
3804 }
Michal Vasko88c29542015-11-27 14:57:53 +01003805 /* HACK for unres */
3806 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003807 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko3767fb22016-07-21 12:10:57 +02003808 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003809 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 goto error;
3811 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003812 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 } else if (!strcmp(sub->name, "units")) {
3814 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003815 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 goto error;
3817 }
3818 GETVAL(value, sub, "name");
3819 llist->units = lydict_insert(module->ctx, value, strlen(value));
3820 } else if (!strcmp(sub->name, "ordered-by")) {
3821 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003822 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003823 goto error;
3824 }
3825 /* just checking the flags in llist is not sufficient, we would
3826 * allow multiple ordered-by statements with the "system" value
3827 */
3828 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003829
Radek Krejci1574a8d2015-08-03 14:16:52 +02003830 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3832 * state data
3833 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003834 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 continue;
3836 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 GETVAL(value, sub, "value");
3839 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003840 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003842 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003844 } /* else system is the default value, so we can ignore it */
3845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 } else if (!strcmp(sub->name, "must")) {
3847 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003848 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003849 } else if (!strcmp(sub->name, "if-feature")) {
3850 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003852 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
3853 c_dflt++;
3854 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003856 } else if (!strcmp(sub->name, "min-elements")) {
3857 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003858 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 goto error;
3860 }
3861 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 GETVAL(value, sub, "value");
3864 while (isspace(value[0])) {
3865 value++;
3866 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 /* convert it to uint32_t */
3869 errno = 0;
3870 endptr = NULL;
3871 val = strtoul(value, &endptr, 10);
3872 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003873 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 goto error;
3875 }
3876 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003877 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003878 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3879 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003880 goto error;
3881 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 } else if (!strcmp(sub->name, "max-elements")) {
3883 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003884 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003885 goto error;
3886 }
3887 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 GETVAL(value, sub, "value");
3890 while (isspace(value[0])) {
3891 value++;
3892 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003893
Radek Krejci0d7b2472016-02-12 11:11:03 +01003894 if (!strcmp(value, "unbounded")) {
3895 llist->max = 0;
3896 } else {
3897 /* convert it to uint32_t */
3898 errno = 0;
3899 endptr = NULL;
3900 val = strtoul(value, &endptr, 10);
3901 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003902 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003903 goto error;
3904 }
3905 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003906 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003907 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3908 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003909 goto error;
3910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003912 } else if (!strcmp(sub->name, "when")) {
3913 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003914 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003915 goto error;
3916 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003917
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003918 llist->when = read_yin_when(module, sub);
3919 if (!llist->when) {
3920 goto error;
3921 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003923 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003926
Michal Vasko88c29542015-11-27 14:57:53 +01003927 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003931 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003932 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003933 goto error;
3934 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 /* middle part - process nodes with cardinality of 0..n */
3937 if (c_must) {
3938 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003939 if (!llist->must) {
3940 LOGMEM;
3941 goto error;
3942 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003944 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003945 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3946 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003947 LOGMEM;
3948 goto error;
3949 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003950 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003951 if (c_dflt) {
3952 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
3953 if (!llist->dflt) {
3954 LOGMEM;
3955 goto error;
3956 }
3957 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003958
Radek Krejci73adb602015-07-02 18:07:40 +02003959 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003961 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3962 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 if (r) {
3964 goto error;
3965 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003966 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003967 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3968 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003969 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003970 goto error;
3971 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003972 } else if (!strcmp(sub->name, "default")) {
3973 GETVAL(value, sub, "value");
3974
3975 /* check for duplicity */
3976 for (r = 0; r < llist->dflt_size; r++) {
3977 if (ly_strequal(llist->dflt[r], value, 1)) {
3978 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3979 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3980 goto error;
3981 }
3982 }
3983 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
3984 }
3985 }
3986
3987 if (llist->dflt_size && llist->min) {
Radek Krejci200bf712016-08-16 17:11:04 +02003988 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "leaf-list");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003989 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3990 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
3991 goto error;
3992 }
3993
3994 /* check default value (if not defined, there still could be some restrictions
3995 * that need to be checked against a default value from a derived type) */
3996 for (r = 0; r < llist->dflt_size; r++) {
3997 if (unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, llist->dflt[r]) == -1) {
3998 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003999 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004001
Michal Vasko508a50d2016-09-07 14:50:33 +02004002 /* check XPath dependencies */
4003 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4004 goto error;
4005 }
4006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004007 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004008
4009error:
4010
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004011 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004013 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004014}
4015
Michal Vasko0d343d12015-08-24 14:57:36 +02004016/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004017static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004018read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4019 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004020{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004021 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004022 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004024 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004025 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02004027 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 char *auxs;
4029 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004031 /* init */
4032 memset(&root, 0, sizeof root);
4033 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004036 if (!list) {
4037 LOGMEM;
4038 return NULL;
4039 }
Radek Krejci76512572015-08-04 09:47:08 +02004040 list->nodetype = LYS_LIST;
4041 list->prev = (struct lys_node *)list;
4042 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004043
Michal Vaskoe0c59842015-09-24 13:52:20 +02004044 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
4045 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004046 goto error;
4047 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004048
Radek Krejcia9544502015-08-14 08:24:29 +02004049 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4050
Radek Krejciadb30652016-07-11 15:27:07 +02004051 /* insert the node into the schema tree */
4052 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4053 goto error;
4054 }
4055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004056 /* process list's specific children */
4057 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004058 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4059 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004060 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004061 continue;
4062 }
4063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 /* data statements */
4065 if (!strcmp(sub->name, "container") ||
4066 !strcmp(sub->name, "leaf-list") ||
4067 !strcmp(sub->name, "leaf") ||
4068 !strcmp(sub->name, "list") ||
4069 !strcmp(sub->name, "choice") ||
4070 !strcmp(sub->name, "uses") ||
4071 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004072 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004073 !strcmp(sub->name, "action") ||
4074 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004075 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004076 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004078 /* array counters */
4079 } else if (!strcmp(sub->name, "key")) {
4080 /* check cardinality 0..1 */
4081 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004082 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004083 goto error;
4084 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02004085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004086 /* count the number of keys */
4087 GETVAL(value, sub, "value");
4088 key_str = value;
4089 while ((value = strpbrk(value, " \t\n"))) {
4090 list->keys_size++;
4091 while (isspace(*value)) {
4092 value++;
4093 }
4094 }
4095 list->keys_size++;
4096 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004097 if (!list->keys) {
4098 LOGMEM;
4099 goto error;
4100 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004101 } else if (!strcmp(sub->name, "unique")) {
4102 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004103 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004104 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004105 } else if (!strcmp(sub->name, "typedef")) {
4106 c_tpdf++;
4107 } else if (!strcmp(sub->name, "must")) {
4108 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004109 } else if (!strcmp(sub->name, "if-feature")) {
4110 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004112 /* optional stetments */
4113 } else if (!strcmp(sub->name, "ordered-by")) {
4114 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004115 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004116 goto error;
4117 }
4118 /* just checking the flags in llist is not sufficient, we would
4119 * allow multiple ordered-by statements with the "system" value
4120 */
4121 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004122
Radek Krejci1574a8d2015-08-03 14:16:52 +02004123 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004124 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4125 * state data
4126 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004127 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 continue;
4129 }
Radek Krejci345ad742015-06-03 11:04:18 +02004130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 GETVAL(value, sub, "value");
4132 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004133 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004134 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004135 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004136 goto error;
4137 }
4138 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004139 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004140 } else if (!strcmp(sub->name, "min-elements")) {
4141 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004142 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004143 goto error;
4144 }
4145 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004147 GETVAL(value, sub, "value");
4148 while (isspace(value[0])) {
4149 value++;
4150 }
Radek Krejci345ad742015-06-03 11:04:18 +02004151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004152 /* convert it to uint32_t */
4153 errno = 0;
4154 auxs = NULL;
4155 val = strtoul(value, &auxs, 10);
4156 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004157 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004158 goto error;
4159 }
4160 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004161 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004162 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4163 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004164 lyxml_free(module->ctx, sub);
4165 goto error;
4166 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004167 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 } else if (!strcmp(sub->name, "max-elements")) {
4169 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004170 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004171 goto error;
4172 }
4173 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004175 GETVAL(value, sub, "value");
4176 while (isspace(value[0])) {
4177 value++;
4178 }
Radek Krejci345ad742015-06-03 11:04:18 +02004179
Radek Krejci0d7b2472016-02-12 11:11:03 +01004180 if (!strcmp(value, "unbounded")) {
4181 list->max = 0;;
4182 } else {
4183 /* convert it to uint32_t */
4184 errno = 0;
4185 auxs = NULL;
4186 val = strtoul(value, &auxs, 10);
4187 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004188 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004189 goto error;
4190 }
4191 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004192 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004193 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4194 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004195 goto error;
4196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004197 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004198 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004199 } else if (!strcmp(sub->name, "when")) {
4200 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004201 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004202 goto error;
4203 }
4204
4205 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004206 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004207 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004208 goto error;
4209 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004210 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004211 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004212 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004213 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 }
4215 }
Radek Krejci345ad742015-06-03 11:04:18 +02004216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004217 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004218 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004219 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004220 goto error;
4221 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004223 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4224 if (c_tpdf) {
4225 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004226 if (!list->tpdf) {
4227 LOGMEM;
4228 goto error;
4229 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004231 if (c_must) {
4232 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004233 if (!list->must) {
4234 LOGMEM;
4235 goto error;
4236 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004237 }
4238 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004239 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4240 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004241 LOGMEM;
4242 goto error;
4243 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004244 }
Radek Krejci73adb602015-07-02 18:07:40 +02004245 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004246 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004247 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4248 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004249 if (r) {
4250 goto error;
4251 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004252 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004253 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
4254 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004255 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004256 goto error;
4257 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004258 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004259 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4260 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004261 if (r) {
4262 goto error;
4263 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004264 }
4265 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004267 /* last part - process data nodes */
4268 LY_TREE_FOR_SAFE(root.child, next, sub) {
4269 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004270 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004272 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004273 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004274 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004275 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004276 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004277 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004278 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004279 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004280 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004281 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004282 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004284 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4285 } else if (!strcmp(sub->name, "anydata")) {
4286 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004287 } else if (!strcmp(sub->name, "action")) {
4288 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004289 } else if (!strcmp(sub->name, "notification")) {
4290 node = read_yin_notif(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004291 } else {
4292 LOGINT;
4293 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004294 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004295 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 goto error;
4297 }
Radek Krejci73adb602015-07-02 18:07:40 +02004298
Michal Vasko345da0a2015-12-02 10:35:55 +01004299 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004300 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004301
Radek Krejci461efb92016-02-12 15:52:18 +01004302 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004303 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004304 goto error;
4305 }
4306 } /* 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 +02004307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 /* process unique statements */
4309 if (c_uniq) {
4310 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004311 if (!list->unique) {
4312 LOGMEM;
4313 goto error;
4314 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004315
Radek Krejci461efb92016-02-12 15:52:18 +01004316 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4317 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4318 list->unique_size++;
4319 if (r) {
4320 goto error;
4321 }
4322
4323 lyxml_free(module->ctx, sub);
4324 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004326
Michal Vasko508a50d2016-09-07 14:50:33 +02004327 /* check XPath dependencies */
4328 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4329 goto error;
4330 }
4331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004332 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004333
4334error:
4335
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004336 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004338 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004339 }
4340 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004341 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004345}
4346
Michal Vasko0d343d12015-08-24 14:57:36 +02004347/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004348static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004349read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4350 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004351{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004353 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004354 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004355 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004356 const char *value;
4357 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004358 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 /* init */
4361 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004363 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004364 if (!cont) {
4365 LOGMEM;
4366 return NULL;
4367 }
Radek Krejci76512572015-08-04 09:47:08 +02004368 cont->nodetype = LYS_CONTAINER;
4369 cont->prev = (struct lys_node *)cont;
4370 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004371
Michal Vaskoe0c59842015-09-24 13:52:20 +02004372 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
4373 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 goto error;
4375 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004376
Radek Krejcia9544502015-08-14 08:24:29 +02004377 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4378
Radek Krejciadb30652016-07-11 15:27:07 +02004379 /* insert the node into the schema tree */
4380 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4381 goto error;
4382 }
4383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004384 /* process container's specific children */
4385 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02004386 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004387 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004388 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004389 continue;
4390 }
4391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004392 if (!strcmp(sub->name, "presence")) {
4393 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004394 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 goto error;
4396 }
4397 GETVAL(value, sub, "value");
4398 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004399
Michal Vasko345da0a2015-12-02 10:35:55 +01004400 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004401 } else if (!strcmp(sub->name, "when")) {
4402 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004403 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004404 goto error;
4405 }
4406
4407 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004408 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004409 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004410 goto error;
4411 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004412 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004414 /* data statements */
4415 } else if (!strcmp(sub->name, "container") ||
4416 !strcmp(sub->name, "leaf-list") ||
4417 !strcmp(sub->name, "leaf") ||
4418 !strcmp(sub->name, "list") ||
4419 !strcmp(sub->name, "choice") ||
4420 !strcmp(sub->name, "uses") ||
4421 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004422 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004423 !strcmp(sub->name, "action") ||
4424 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004425 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004426 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004428 /* array counters */
4429 } else if (!strcmp(sub->name, "typedef")) {
4430 c_tpdf++;
4431 } else if (!strcmp(sub->name, "must")) {
4432 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004433 } else if (!strcmp(sub->name, "if-feature")) {
4434 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004436 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004437 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 }
4439 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4442 if (c_tpdf) {
4443 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004444 if (!cont->tpdf) {
4445 LOGMEM;
4446 goto error;
4447 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 }
4449 if (c_must) {
4450 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004451 if (!cont->must) {
4452 LOGMEM;
4453 goto error;
4454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004455 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004456 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004457 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4458 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004459 LOGMEM;
4460 goto error;
4461 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004462 }
Radek Krejci800af702015-06-02 13:46:01 +02004463
Radek Krejci73adb602015-07-02 18:07:40 +02004464 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004466 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4467 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 if (r) {
4469 goto error;
4470 }
4471 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004472 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4473 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 if (r) {
4475 goto error;
4476 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004477 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004478 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
4479 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004480 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004481 goto error;
4482 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004483 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486 /* last part - process data nodes */
4487 LY_TREE_FOR_SAFE(root.child, next, sub) {
4488 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004489 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004490 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004491 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004493 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004495 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004497 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004498 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004499 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004501 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004502 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004503 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4504 } else if (!strcmp(sub->name, "anydata")) {
4505 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004506 } else if (!strcmp(sub->name, "action")) {
4507 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004508 } else if (!strcmp(sub->name, "notification")) {
4509 node = read_yin_notif(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004511 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 goto error;
4513 }
Radek Krejci73adb602015-07-02 18:07:40 +02004514
Michal Vasko345da0a2015-12-02 10:35:55 +01004515 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004517
Michal Vasko508a50d2016-09-07 14:50:33 +02004518 /* check XPath dependencies */
4519 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4520 goto error;
4521 }
4522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004524
4525error:
4526
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004527 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004529 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004533}
4534
Michal Vasko0d343d12015-08-24 14:57:36 +02004535/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004536static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02004537read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004538 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004539{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004541 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004542 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004543 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 int r;
4545 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004547 /* init */
4548 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004551 if (!grp) {
4552 LOGMEM;
4553 return NULL;
4554 }
Radek Krejci76512572015-08-04 09:47:08 +02004555 grp->nodetype = LYS_GROUPING;
4556 grp->prev = (struct lys_node *)grp;
4557 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004558
Michal Vasko71e1aa82015-08-12 12:17:51 +02004559 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 goto error;
4561 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004562
Radek Krejcia9544502015-08-14 08:24:29 +02004563 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4564
Radek Krejciadb30652016-07-11 15:27:07 +02004565 /* insert the node into the schema tree */
4566 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4567 goto error;
4568 }
4569
Radek Krejci1d82ef62015-08-07 14:44:40 +02004570 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004571 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4572 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004573 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004574 continue;
4575 }
4576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 /* data statements */
4578 if (!strcmp(sub->name, "container") ||
4579 !strcmp(sub->name, "leaf-list") ||
4580 !strcmp(sub->name, "leaf") ||
4581 !strcmp(sub->name, "list") ||
4582 !strcmp(sub->name, "choice") ||
4583 !strcmp(sub->name, "uses") ||
4584 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004585 !strcmp(sub->name, "anyxml") ||
4586 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004587 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004588 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004589
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590 /* array counters */
4591 } else if (!strcmp(sub->name, "typedef")) {
4592 c_tpdf++;
4593 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004594 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004595 goto error;
4596 }
4597 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4600 if (c_tpdf) {
4601 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004602 if (!grp->tpdf) {
4603 LOGMEM;
4604 goto error;
4605 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004608 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4609 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004610 if (r) {
4611 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004616 if (!root.child) {
4617 LOGWRN("Grouping \"%s\" without children.", retval->name);
4618 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 LY_TREE_FOR_SAFE(root.child, next, sub) {
4620 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004621 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004623 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004625 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004631 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004635 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4636 } else if (!strcmp(sub->name, "anydata")) {
4637 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004638 } else if (!strcmp(sub->name, "action")) {
4639 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004641 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 goto error;
4643 }
Radek Krejci73adb602015-07-02 18:07:40 +02004644
Michal Vasko345da0a2015-12-02 10:35:55 +01004645 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004649
4650error:
4651
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004652 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004654 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004658}
4659
Michal Vasko0d343d12015-08-24 14:57:36 +02004660/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004661static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004662read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4663 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004664{
Radek Krejcie0674f82015-06-15 13:58:51 +02004665 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004666 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004667 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004668 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004669 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004670 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004671
Radek Krejcie0674f82015-06-15 13:58:51 +02004672 /* init */
4673 memset(&root, 0, sizeof root);
4674
Michal Vasko38d01f72015-06-15 09:41:06 +02004675 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004676 if (!inout) {
4677 LOGMEM;
4678 return NULL;
4679 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004680 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004681
4682 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004683 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004684 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004685 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004686 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004687 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004688 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004689 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004690 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004691 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004692 }
4693
Radek Krejci76512572015-08-04 09:47:08 +02004694 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004695
Radek Krejci6a113852015-07-03 16:04:20 +02004696 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004697 goto error;
4698 }
4699
Radek Krejcia9544502015-08-14 08:24:29 +02004700 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4701
Radek Krejciadb30652016-07-11 15:27:07 +02004702 /* insert the node into the schema tree */
4703 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4704 goto error;
4705 }
4706
Michal Vasko38d01f72015-06-15 09:41:06 +02004707 /* data statements */
4708 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004709 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4710 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004711 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004712 continue;
4713 }
4714
Michal Vasko38d01f72015-06-15 09:41:06 +02004715 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 !strcmp(sub->name, "leaf-list") ||
4717 !strcmp(sub->name, "leaf") ||
4718 !strcmp(sub->name, "list") ||
4719 !strcmp(sub->name, "choice") ||
4720 !strcmp(sub->name, "uses") ||
4721 !strcmp(sub->name, "grouping") ||
4722 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004723 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004724 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004727 } else if (!strcmp(sub->name, "typedef")) {
4728 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004729
Radek Krejci1a31efe2016-07-29 11:04:16 +02004730 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004731 c_must++;
4732
Michal Vasko38d01f72015-06-15 09:41:06 +02004733 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004734 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004735 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004736 }
4737 }
4738
4739 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4740 if (c_tpdf) {
4741 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004742 if (!inout->tpdf) {
4743 LOGMEM;
4744 goto error;
4745 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004746 }
Radek Krejci19332802016-07-29 10:39:46 +02004747 if (c_must) {
4748 inout->must = calloc(c_must, sizeof *inout->must);
4749 if (!inout->must) {
4750 LOGMEM;
4751 goto error;
4752 }
4753 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004754
Radek Krejci73adb602015-07-02 18:07:40 +02004755 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004756 if (!strcmp(sub->name, "must")) {
4757 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4758 inout->must_size++;
4759 if (r) {
4760 goto error;
4761 }
4762 } else { /* typedef */
4763 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4764 inout->tpdf_size++;
4765 if (r) {
4766 goto error;
4767 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004768 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004769 }
4770
4771 /* last part - process data nodes */
4772 LY_TREE_FOR_SAFE(root.child, next, sub) {
4773 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004775 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004776 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004777 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004778 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004779 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004780 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004781 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004782 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004783 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004784 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004785 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004786 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004787 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004788 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4789 } else if (!strcmp(sub->name, "anydata")) {
4790 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004791 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004792 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004793 goto error;
4794 }
Radek Krejci73adb602015-07-02 18:07:40 +02004795
Michal Vasko345da0a2015-12-02 10:35:55 +01004796 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004797 }
4798
Michal Vasko508a50d2016-09-07 14:50:33 +02004799 /* check XPath dependencies */
4800 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4801 goto error;
4802 }
4803
Michal Vasko38d01f72015-06-15 09:41:06 +02004804 return retval;
4805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004807
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004808 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004809 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004810 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004811 }
4812
4813 return NULL;
4814}
4815
Michal Vasko0d343d12015-08-24 14:57:36 +02004816/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004817static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004818read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4819 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004820{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004821 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004822 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004823 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004824 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004825 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004826 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004827
Michal Vaskoc6551b32015-06-16 10:51:43 +02004828 memset(&root, 0, sizeof root);
4829
Michal Vasko0ea41032015-06-16 08:53:55 +02004830 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004831 if (!notif) {
4832 LOGMEM;
4833 return NULL;
4834 }
Radek Krejci76512572015-08-04 09:47:08 +02004835 notif->nodetype = LYS_NOTIF;
4836 notif->prev = (struct lys_node *)notif;
4837 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004838
Radek Krejci6a113852015-07-03 16:04:20 +02004839 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004840 goto error;
4841 }
4842
Radek Krejcia9544502015-08-14 08:24:29 +02004843 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4844
Radek Krejciadb30652016-07-11 15:27:07 +02004845 /* insert the node into the schema tree */
4846 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4847 goto error;
4848 }
4849
Michal Vasko0ea41032015-06-16 08:53:55 +02004850 /* process rpc's specific children */
4851 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004852 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4853 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004854 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004855 continue;
4856 }
4857
Michal Vasko0ea41032015-06-16 08:53:55 +02004858 /* data statements */
4859 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 !strcmp(sub->name, "leaf-list") ||
4861 !strcmp(sub->name, "leaf") ||
4862 !strcmp(sub->name, "list") ||
4863 !strcmp(sub->name, "choice") ||
4864 !strcmp(sub->name, "uses") ||
4865 !strcmp(sub->name, "grouping") ||
4866 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004867 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004868 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004871 } else if (!strcmp(sub->name, "typedef")) {
4872 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004873 } else if (!strcmp(sub->name, "if-feature")) {
4874 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004875 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004876 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004877 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004878 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004879 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004880 }
4881 }
4882
4883 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4884 if (c_tpdf) {
4885 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004886 if (!notif->tpdf) {
4887 LOGMEM;
4888 goto error;
4889 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004890 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004891 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004892 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4893 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004894 LOGMEM;
4895 goto error;
4896 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004897 }
Radek Krejci19332802016-07-29 10:39:46 +02004898 if (c_must) {
4899 notif->must = calloc(c_must, sizeof *notif->must);
4900 if (!notif->must) {
4901 LOGMEM;
4902 goto error;
4903 }
4904 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004905
Radek Krejci73adb602015-07-02 18:07:40 +02004906 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004907 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004908 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4909 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004910 if (r) {
4911 goto error;
4912 }
Radek Krejci96299152016-06-22 10:17:50 +02004913 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004914 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4915 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004916 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004917 goto error;
4918 }
Radek Krejci19332802016-07-29 10:39:46 +02004919 } else if (!strcmp(sub->name, "must")) {
4920 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4921 notif->must_size++;
4922 if (r) {
4923 goto error;
4924 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004925 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004926 }
4927
4928 /* last part - process data nodes */
4929 LY_TREE_FOR_SAFE(root.child, next, sub) {
4930 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004931 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004932 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004933 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004934 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004935 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004936 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004937 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004938 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004939 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004940 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004941 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004942 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004943 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004944 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004945 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4946 } else if (!strcmp(sub->name, "anydata")) {
4947 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004948 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004949 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004950 goto error;
4951 }
Radek Krejci73adb602015-07-02 18:07:40 +02004952
Michal Vasko345da0a2015-12-02 10:35:55 +01004953 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004954 }
4955
Michal Vasko508a50d2016-09-07 14:50:33 +02004956 /* check XPath dependencies */
4957 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4958 goto error;
4959 }
4960
Michal Vasko0ea41032015-06-16 08:53:55 +02004961 return retval;
4962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004963error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004964
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004965 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004966 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004967 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004968 }
4969
4970 return NULL;
4971}
4972
Michal Vasko0d343d12015-08-24 14:57:36 +02004973/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004974static struct lys_node *
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004975read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4976 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004977{
Radek Krejcie0674f82015-06-15 13:58:51 +02004978 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004979 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004980 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004981 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004982 int r;
Pavol Vican3cb70c72016-09-05 11:32:52 +02004983 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004984
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004985 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02004986 if (module->version < 2) {
Michal Vaskobb174852016-07-25 11:00:21 +02004987 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
4988 return NULL;
4989 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004990 for (node = parent; node; node = lys_parent(node)) {
4991 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
4992 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
4993 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
4994 return NULL;
4995 }
4996 }
4997 }
4998
Radek Krejcie0674f82015-06-15 13:58:51 +02004999 /* init */
5000 memset(&root, 0, sizeof root);
5001
Michal Vasko38d01f72015-06-15 09:41:06 +02005002 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005003 if (!rpc) {
5004 LOGMEM;
5005 return NULL;
5006 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005007 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005008 rpc->prev = (struct lys_node *)rpc;
5009 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005010
Radek Krejci6a113852015-07-03 16:04:20 +02005011 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005012 goto error;
5013 }
5014
Radek Krejcia9544502015-08-14 08:24:29 +02005015 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5016
Radek Krejciadb30652016-07-11 15:27:07 +02005017 /* insert the node into the schema tree */
5018 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5019 goto error;
5020 }
5021
Michal Vasko38d01f72015-06-15 09:41:06 +02005022 /* process rpc's specific children */
5023 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005024 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5025 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005026 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005027 continue;
5028 }
5029
Michal Vasko38d01f72015-06-15 09:41:06 +02005030 if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005031 if (c_input) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005032 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005033 goto error;
5034 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005035 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005036 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005037 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005038 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005039 if (c_output) {
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_output++;
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
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005048 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005049 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005050 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005052 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005053 } else if (!strcmp(sub->name, "typedef")) {
5054 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005055 } else if (!strcmp(sub->name, "if-feature")) {
5056 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005057 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005058 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005059 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005060 }
5061 }
5062
5063 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5064 if (c_tpdf) {
5065 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005066 if (!rpc->tpdf) {
5067 LOGMEM;
5068 goto error;
5069 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005070 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005071 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005072 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5073 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005074 LOGMEM;
5075 goto error;
5076 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005077 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005078
Radek Krejci73adb602015-07-02 18:07:40 +02005079 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005080 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005081 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5082 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005083 if (r) {
5084 goto error;
5085 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005086 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005087 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
5088 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005089 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005090 goto error;
5091 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005092 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005093 }
5094
5095 /* last part - process data nodes */
5096 LY_TREE_FOR_SAFE(root.child, next, sub) {
5097 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005098 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005099 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005100 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005101 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005102 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005103 goto error;
5104 }
Radek Krejci73adb602015-07-02 18:07:40 +02005105
Michal Vasko345da0a2015-12-02 10:35:55 +01005106 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005107 }
5108
Michal Vasko38d01f72015-06-15 09:41:06 +02005109 return retval;
5110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005111error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005112
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005113 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005114 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005115 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005116 }
5117
5118 return NULL;
5119}
5120
Michal Vasko0d343d12015-08-24 14:57:36 +02005121/* logs directly
5122 *
Radek Krejci74705112015-06-05 10:25:44 +02005123 * resolve - referenced grouping should be bounded to the namespace (resolved)
5124 * only when uses does not appear in grouping. In a case of grouping's uses,
5125 * we just get information but we do not apply augment or refine to it.
5126 */
Radek Krejci76512572015-08-04 09:47:08 +02005127static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005128read_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 +02005129{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005130 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005131 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005132 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005133 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005134 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005138 if (!uses) {
5139 LOGMEM;
5140 return NULL;
5141 }
Radek Krejci76512572015-08-04 09:47:08 +02005142 uses->nodetype = LYS_USES;
5143 uses->prev = (struct lys_node *)uses;
5144 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005145
Radek Krejcia9544502015-08-14 08:24:29 +02005146 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005147 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005148
Michal Vaskoe0c59842015-09-24 13:52:20 +02005149 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02005150 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 goto error;
5152 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005153
Radek Krejcia9544502015-08-14 08:24:29 +02005154 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5155
Radek Krejciadb30652016-07-11 15:27:07 +02005156 /* insert the node into the schema tree */
5157 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5158 goto error;
5159 }
5160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005162 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005163 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5164 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005165 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005166 continue;
5167 }
5168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 if (!strcmp(sub->name, "refine")) {
5170 c_ref++;
5171 } else if (!strcmp(sub->name, "augment")) {
5172 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005173 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005174 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005175 } else if (!strcmp(sub->name, "when")) {
5176 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005177 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005178 goto error;
5179 }
5180
5181 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005182 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005183 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005184 goto error;
5185 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005186 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005187 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005188 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005189 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 }
5191 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 /* process properties with cardinality 0..n */
5194 if (c_ref) {
5195 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005196 if (!uses->refine) {
5197 LOGMEM;
5198 goto error;
5199 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 }
5201 if (c_aug) {
5202 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005203 if (!uses->augment) {
5204 LOGMEM;
5205 goto error;
5206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005208 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005209 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5210 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005211 LOGMEM;
5212 goto error;
5213 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005214 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005215
Radek Krejcia9544502015-08-14 08:24:29 +02005216 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005218 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005219 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005220 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005221 goto error;
5222 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005223 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005224 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5225 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005226 if (r) {
5227 goto error;
5228 }
5229 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005230 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
5231 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005232 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005233 goto error;
5234 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005235 }
5236 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005237
Radek Krejci48464ed2016-03-17 15:44:09 +01005238 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005239 goto error;
5240 }
Radek Krejci74705112015-06-05 10:25:44 +02005241
Michal Vasko508a50d2016-09-07 14:50:33 +02005242 /* check XPath dependencies */
5243 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5244 goto error;
5245 }
5246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005248
5249error:
5250
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005251 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005254}
5255
Michal Vasko0d343d12015-08-24 14:57:36 +02005256/* logs directly
5257 *
5258 * common code for yin_read_module() and yin_read_submodule()
5259 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005260static int
Radek Krejcic071c542016-01-27 14:57:51 +01005261read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5262 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005263{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005265 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005266 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005267 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005268 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005270 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005271 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005272 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005273 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02005274 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 +02005275
Radek Krejcic071c542016-01-27 14:57:51 +01005276 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005277 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 /* init */
5280 memset(&root, 0, sizeof root);
5281 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005282 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02005283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005284 /*
5285 * in the first run, we process elements with cardinality of 1 or 0..1 and
5286 * count elements with cardinality 0..n. Data elements (choices, containers,
5287 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5288 * need have all top-level and groupings already prepared at that time. In
5289 * the middle loop, we process other elements with carinality of 0..n since
5290 * we need to allocate arrays to store them.
5291 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005292 LY_TREE_FOR_SAFE(yin->child, next, child) {
5293 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005294 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005295 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 continue;
5297 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005298
Radek Krejcic071c542016-01-27 14:57:51 +01005299 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005301 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005302 goto error;
5303 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005304 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005305 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005306 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005307 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 if (module->prefix) {
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, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005313 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005314 goto error;
5315 }
5316 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005317 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005318 } else if (submodule && !strcmp(child->name, "belongs-to")) {
5319 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005320 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005321 goto error;
5322 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005323 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005324 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005325 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005326 goto error;
5327 }
Radek Krejcif3886932015-06-04 17:36:06 +02005328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005329 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005330 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005331 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005332 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005333 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005334 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005335 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005336 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005337 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005338 goto error;
5339 }
5340 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005341 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 /* check here differs from a generic prefix check, since this prefix
5343 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005344 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005345 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 goto error;
5347 }
Radek Krejcic071c542016-01-27 14:57:51 +01005348 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005351 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005352
5353 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005354 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005356 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005358 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005359 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005360 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005361 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005362 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005363 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005364 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005365 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005366 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005367 lyxml_unlink_elem(ctx, child, 2);
5368 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005369
Radek Krejci1d82ef62015-08-07 14:44:40 +02005370 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005371 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005372 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02005373 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005375 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005376 } else if (!strcmp(child->name, "container") ||
5377 !strcmp(child->name, "leaf-list") ||
5378 !strcmp(child->name, "leaf") ||
5379 !strcmp(child->name, "list") ||
5380 !strcmp(child->name, "choice") ||
5381 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005382 !strcmp(child->name, "anyxml") ||
5383 !strcmp(child->name, "rpc") ||
5384 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005385 lyxml_unlink_elem(ctx, child, 2);
5386 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005387
Radek Krejci1d82ef62015-08-07 14:44:40 +02005388 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005389 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005390 lyxml_unlink_elem(ctx, child, 2);
5391 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005393 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005394 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005395 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005396 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 goto error;
5398 }
Radek Krejcic071c542016-01-27 14:57:51 +01005399 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005400 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005401 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005402 goto error;
5403 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005404 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005405 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005406 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005407 goto error;
5408 }
Radek Krejcic071c542016-01-27 14:57:51 +01005409 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005410 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005411 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005412 goto error;
5413 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005414 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005415 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005416 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005417 goto error;
5418 }
Radek Krejcic071c542016-01-27 14:57:51 +01005419 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005420 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005421 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005422 goto error;
5423 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005424 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005425 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005426 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 goto error;
5428 }
Radek Krejcic071c542016-01-27 14:57:51 +01005429 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005430 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005431 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005432 goto error;
5433 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005434 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005435 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005436 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005437 goto error;
5438 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005439 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005440 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005441 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005442 goto error;
5443 }
Radek Krejcic071c542016-01-27 14:57:51 +01005444 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005445 if (!strcmp(value, "1")) {
5446 if (submodule) {
5447 if (module->version > 1) {
5448 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5449 goto error;
5450 }
5451 } else {
5452 module->version = 1;
5453 }
5454 } else {
5455 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005456 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005457 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5458 goto error;
5459 }
5460 } else {
5461 module->version = 2;
5462 }
5463 }
5464
Michal Vasko345da0a2015-12-02 10:35:55 +01005465 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005466
Radek Krejci1d82ef62015-08-07 14:44:40 +02005467 } else if (!strcmp(child->name, "extension")) {
5468 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005469
Radek Krejci3d468122015-10-02 13:36:12 +02005470 /* we have the following supported (hardcoded) extensions: */
5471 /* ietf-netconf's get-filter-element-attributes */
5472 if (!strcmp(module->ns, LY_NSNC) &&
5473 !strcmp(value, "get-filter-element-attributes")) {
5474 LOGDBG("NETCONF filter extension found");
5475 /* NACM's default-deny-write and default-deny-all */
5476 } else if (!strcmp(module->ns, LY_NSNACM) &&
5477 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5478 LOGDBG("NACM extension found");
5479 /* other extensions are not supported, so inform about such an extension */
5480 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005481 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005482 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005483 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005484 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005485 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005486 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005487 }
5488 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005489
Radek Krejcic071c542016-01-27 14:57:51 +01005490 /* check for mandatory statements */
5491 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005492 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005493 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005494 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005495 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005496 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005497 goto error;
5498 }
5499 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005500 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005501 goto error;
5502 }
5503 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005505 /* allocate arrays for elements with cardinality of 0..n */
5506 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005507 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5508 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005509 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005510 LOGMEM;
5511 goto error;
5512 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005513 /* set stop block for possible realloc */
5514 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005515 }
5516 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005517 trg->rev = calloc(c_rev, sizeof *trg->rev);
5518 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005519 LOGMEM;
5520 goto error;
5521 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005522 }
5523 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005524 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5525 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005526 LOGMEM;
5527 goto error;
5528 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 }
5530 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005531 trg->ident = calloc(c_ident, sizeof *trg->ident);
5532 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005533 LOGMEM;
5534 goto error;
5535 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005536 }
5537 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005538 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5539 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005540 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005541 LOGMEM;
5542 goto error;
5543 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005544 /* set stop block for possible realloc */
5545 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005546 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005547 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005548 trg->augment = calloc(c_aug, sizeof *trg->augment);
5549 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005550 LOGMEM;
5551 goto error;
5552 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005553 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005554 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005555 trg->features = calloc(c_ftrs, sizeof *trg->features);
5556 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005557 LOGMEM;
5558 goto error;
5559 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005560 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005561 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005562 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5563 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005564 LOGMEM;
5565 goto error;
5566 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005567 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005568
Michal Vasko2f7925f2015-10-21 15:06:56 +02005569 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5570 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005571 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005572 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5573 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005574 if (r) {
5575 goto error;
5576 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005577
Radek Krejci1d82ef62015-08-07 14:44:40 +02005578 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005579 memset(&inc, 0, sizeof inc);
5580 /* 1) pass module, not trg, since we want to pass the main module
5581 * 2) we cannot pass directly the structure in the array since
5582 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01005583 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005584 if (!r) {
5585 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02005586 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
5587 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005588 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005589 goto error;
5590 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005591
Radek Krejci1d82ef62015-08-07 14:44:40 +02005592 } else if (!strcmp(child->name, "revision")) {
5593 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005594 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005595 goto error;
5596 }
Radek Krejcic071c542016-01-27 14:57:51 +01005597 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005598 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005599 for (i = 0; i < trg->rev_size; i++) {
5600 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005601 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5602 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005603 }
5604 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005605
Radek Krejci1d82ef62015-08-07 14:44:40 +02005606 LY_TREE_FOR(child->child, child2) {
5607 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005608 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005609 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 goto error;
5611 }
Radek Krejcic071c542016-01-27 14:57:51 +01005612 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5613 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 goto error;
5615 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005616 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005617 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005618 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005619 goto error;
5620 }
Radek Krejcic071c542016-01-27 14:57:51 +01005621 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5622 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005623 goto error;
5624 }
5625 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005626 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005627 goto error;
5628 }
5629 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005631 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005632 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005633 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005634 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005635 if (!value) {
5636 LOGMEM;
5637 goto error;
5638 }
Radek Krejcic071c542016-01-27 14:57:51 +01005639 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5640 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005641 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005642
Radek Krejci749190d2016-02-18 16:26:25 +01005643 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005644 value = trg->rev[0].dsc;
5645 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5646 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005647 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005648
Radek Krejci749190d2016-02-18 16:26:25 +01005649 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005650 value = trg->rev[0].ref;
5651 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5652 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005653 }
5654 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005655
Radek Krejcic071c542016-01-27 14:57:51 +01005656 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005657
Radek Krejci1d82ef62015-08-07 14:44:40 +02005658 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005659 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5660 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005661 if (r) {
5662 goto error;
5663 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005664
Radek Krejci1d82ef62015-08-07 14:44:40 +02005665 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005666 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5667 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005668 if (r) {
5669 goto error;
5670 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005671
Radek Krejci1d82ef62015-08-07 14:44:40 +02005672 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005673 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5674 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005675 if (r) {
5676 goto error;
5677 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005678
Radek Krejci1d82ef62015-08-07 14:44:40 +02005679 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005680 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5681 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005682 if (r) {
5683 goto error;
5684 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005685 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005686 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005687
Radek Krejcib8f98c12016-06-24 10:30:46 +02005688 if (!submodule) {
5689 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005690 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005691 if (module->inc_size) {
5692 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5693 if (!module->inc) {
5694 LOGMEM;
5695 goto error;
5696 }
5697 }
5698 if (module->imp_size) {
5699 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5700 if (!module->imp) {
5701 LOGMEM;
5702 goto error;
5703 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005704 }
5705 }
Radek Krejcic071c542016-01-27 14:57:51 +01005706
Radek Krejcif5be10f2015-06-16 13:29:36 +02005707 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005708 * refer to them. Submodule's data nodes are stored in the
5709 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005710 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005711 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005712 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005713 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005714 goto error;
5715 }
Radek Krejci74705112015-06-05 10:25:44 +02005716
Michal Vasko345da0a2015-12-02 10:35:55 +01005717 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005718 }
Radek Krejci74705112015-06-05 10:25:44 +02005719
Radek Krejcif5be10f2015-06-16 13:29:36 +02005720 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005721 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005722
Radek Krejci1d82ef62015-08-07 14:44:40 +02005723 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005724 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005725 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005726 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005727 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005728 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005729 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005730 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005731 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005732 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005733 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005734 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005735 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02005736 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
5737 } else if (!strcmp(child->name, "anydata")) {
5738 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005739 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005740 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005741 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005742 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005743 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005744 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005745 goto error;
5746 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005747
Michal Vasko345da0a2015-12-02 10:35:55 +01005748 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005750
Michal Vasko2f7925f2015-10-21 15:06:56 +02005751 /* ... and finally augments (last, so we can augment our data, for instance) */
5752 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005753 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5754 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005755
Michal Vasko2f7925f2015-10-21 15:06:56 +02005756 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005757 goto error;
5758 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005759 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005760 }
5761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005762 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005763
5764error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005765 /* cleanup */
5766 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005767 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005768 }
5769 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005770 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005771 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005772 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005773 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005774 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005776 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005777}
5778
Michal Vasko0d343d12015-08-24 14:57:36 +02005779/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005780struct lys_submodule *
5781yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005782{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005783 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005784 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005785 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005786
Michal Vasko5a721fd2016-02-16 12:16:48 +01005787 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005788
Radek Krejci722b0072016-02-01 17:09:45 +01005789 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005790 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005791 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005792 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005794 /* check root element */
5795 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005796 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005797 goto error;
5798 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005800 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005801 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005802 goto error;
5803 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005804
Michal Vasko5a721fd2016-02-16 12:16:48 +01005805 submodule = calloc(1, sizeof *submodule);
5806 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005807 LOGMEM;
5808 goto error;
5809 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005810
Michal Vasko5a721fd2016-02-16 12:16:48 +01005811 submodule->ctx = module->ctx;
5812 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5813 submodule->type = 1;
5814 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005815
Michal Vasko5a721fd2016-02-16 12:16:48 +01005816 LOGVRB("Reading submodule \"%s\".", submodule->name);
5817 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005818 goto error;
5819 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005821 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005822 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005823
Michal Vasko5a721fd2016-02-16 12:16:48 +01005824 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005825 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005826
5827error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005828 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005829 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005830 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005831
Michal Vasko5a721fd2016-02-16 12:16:48 +01005832 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005833 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005834 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005835 }
5836
Michal Vasko5a721fd2016-02-16 12:16:48 +01005837 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005838
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005839 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5840 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005841 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005842 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005843}
5844
Michal Vasko0d343d12015-08-24 14:57:36 +02005845/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005846struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005847yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005848{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005849 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005850 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005851 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005852 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005853
Radek Krejcic071c542016-01-27 14:57:51 +01005854 unres = calloc(1, sizeof *unres);
5855 if (!unres) {
5856 LOGMEM;
5857 return NULL;
5858 }
5859
Radek Krejci722b0072016-02-01 17:09:45 +01005860 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005861 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005862 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005863 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005865 /* check root element */
5866 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005867 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005868 goto error;
5869 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005871 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005872 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005873 goto error;
5874 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005876 module = calloc(1, sizeof *module);
5877 if (!module) {
5878 LOGMEM;
5879 goto error;
5880 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005882 module->ctx = ctx;
5883 module->name = lydict_insert(ctx, value, strlen(value));
5884 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005885 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005886
Michal Vasko9f258e42016-02-11 11:36:27 +01005887 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005888 if (read_sub_module(module, NULL, yin, unres)) {
5889 goto error;
5890 }
5891
5892 /* resolve rest of unres items */
5893 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005894 goto error;
5895 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005896
Radek Krejciff4874d2016-03-07 12:30:50 +01005897 if (revision) {
5898 /* check revision of the parsed model */
5899 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005900 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5901 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005902 goto error;
5903 }
5904 }
5905
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005906 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005907 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005908 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005909
Radek Krejci27fe55e2016-09-13 17:13:35 +02005910 if (module->deviation_size && !module->implemented) {
5911 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
5912 /* deviations always causes target to be made implemented,
5913 * but augents and leafrefs not, so we have to apply them now */
5914 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02005915 goto error;
5916 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005917 }
5918
Michal Vasko345da0a2015-12-02 10:35:55 +01005919 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005920 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005921 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005922 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005923
5924error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005925 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005926 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005927 unres_schema_free(module, &unres);
5928
5929 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005930 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005931 return NULL;
5932 }
5933
5934 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005935
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005936 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005937 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005938 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005939}