blob: 82035a78f8dbbd8a93649a8ada86d078090c340b [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 Krejcib8048692015-08-05 13:36:34 +020056static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020057 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 Vaskof02e3742015-08-05 16:27:02 +020072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020073
Michal Vasko0d343d12015-08-24 14:57:36 +020074/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020075static const char *
76read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020077{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020078 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020080 /* there should be <text> child */
81 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010082 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010083 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010084 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020085 } else if (node->child->content) {
86 len = strlen(node->child->content);
87 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010088 } else {
89 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020090 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020091}
92
Michal Vasko0d343d12015-08-24 14:57:36 +020093/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020094static int
Radek Krejci9ff0a922016-07-14 13:08:05 +020095fill_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 +010096{
97 int r;
98 const char *value;
99
100 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100101 if (!(value = transform_schema2json(parent->module, value))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200102error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100103 return EXIT_FAILURE;
104 }
105
Radek Krejci9ff0a922016-07-14 13:08:05 +0200106 r = resolve_iffeature_compile(iffeat, value, parent, unres);
107 lydict_remove(parent->module->ctx, value);
108 if (r) {
109 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100110 }
111
Radek Krejci9ff0a922016-07-14 13:08:05 +0200112 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100113}
114
115/* logs directly */
116static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200117fill_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 +0200118{
Radek Krejci73adb602015-07-02 18:07:40 +0200119 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200120 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100121 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200122
Michal Vasko4cfcd252015-08-03 14:31:10 +0200123 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100124 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200125
Radek Krejci76512572015-08-04 09:47:08 +0200126 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200127 return EXIT_FAILURE;
128 }
Radek Krejci04581c62015-05-22 21:24:00 +0200129
Pavol Vicand6cda452016-07-13 15:08:29 +0200130 if (dup_identities_check(ident->name, module)) {
131 return EXIT_FAILURE;
132 }
133
Radek Krejci73adb602015-07-02 18:07:40 +0200134 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200135 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
136 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200137 continue;
138 }
139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200140 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100141 if (base_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100142 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200143 return EXIT_FAILURE;
144 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100145 base_flag = 1;
146
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200147 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100148 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100149 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200150 return EXIT_FAILURE;
151 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100152
Radek Krejci48464ed2016-03-17 15:44:09 +0100153 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100154 lydict_remove(module->ctx, value);
155 return EXIT_FAILURE;
156 }
157 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200158 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100159 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200160 return EXIT_FAILURE;
161 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200162 }
Radek Krejci04581c62015-05-22 21:24:00 +0200163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200164 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200165
166error:
167 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200168}
169
Michal Vasko0d343d12015-08-24 14:57:36 +0200170/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200171static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200172read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200173{
Radek Krejci73adb602015-07-02 18:07:40 +0200174 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200175 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200176
Radek Krejci73adb602015-07-02 18:07:40 +0200177 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200178 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
179 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200180 continue;
181 }
182
Radek Krejci41726f92015-06-19 13:11:05 +0200183 if (!strcmp(child->name, "description")) {
184 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100185 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200186 return EXIT_FAILURE;
187 }
188 restr->dsc = read_yin_subnode(ctx, child, "text");
189 if (!restr->dsc) {
190 return EXIT_FAILURE;
191 }
192 } else if (!strcmp(child->name, "reference")) {
193 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100194 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200195 return EXIT_FAILURE;
196 }
197 restr->ref = read_yin_subnode(ctx, child, "text");
198 if (!restr->ref) {
199 return EXIT_FAILURE;
200 }
201 } else if (!strcmp(child->name, "error-app-tag")) {
202 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100203 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200204 return EXIT_FAILURE;
205 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200206 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200207 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200208 } else if (!strcmp(child->name, "error-message")) {
209 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100210 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200211 return EXIT_FAILURE;
212 }
213 restr->emsg = read_yin_subnode(ctx, child, "value");
214 if (!restr->emsg) {
215 return EXIT_FAILURE;
216 }
217 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100218 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200219 return EXIT_FAILURE;
220 }
Radek Krejci41726f92015-06-19 13:11:05 +0200221 }
222
223 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200224
225error:
226 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200227}
228
Michal Vasko88c29542015-11-27 14:57:53 +0100229/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
230int
Radek Krejcib8048692015-08-05 13:36:34 +0200231fill_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 +0200232 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200233{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200234 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200235 struct lys_node *siter;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200236 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200237 struct lys_restr **restr;
238 struct lys_type_bit bit;
Radek Krejcifc8d8322016-06-24 11:23:23 +0200239 int i, j, rc, val_set;
Radek Krejcidc008d72016-02-17 13:12:14 +0100240 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200241 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200242 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200243
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200244 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100245 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200246 if (!value) {
247 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200248 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200249
250 i = parse_identifier(value);
251 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100252 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100253 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200254 goto error;
255 }
256 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100257 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200258 if (value[i]) {
259 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100260 name += i;
261 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100262 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100263 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200264 goto error;
265 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200266 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100267 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200268 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200269
Radek Krejci225376f2016-02-16 17:36:22 +0100270 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200271 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100272 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200273 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200274 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100275
276 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200277 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200278 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200279 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100280 ret = EXIT_FAILURE;
281 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200282 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200283 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200284 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200285
Radek Krejcicf509982015-12-15 09:22:44 +0100286 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100287 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100288 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100289 return -1;
290 }
291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200292 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200293 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200294 /* RFC 6020 9.7.4 - bit */
295
296 /* get bit specifications, at least one must be present */
297 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200298 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
299 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100300 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200301 continue;
302 }
303
Radek Krejci994b6f62015-06-18 16:47:27 +0200304 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200305 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200306 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100307 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200308 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200309 }
310 }
Radek Krejciac781922015-07-09 15:35:14 +0200311 if (!type->der->type.der && !type->info.bits.count) {
312 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100313 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200314 goto error;
315 }
Radek Krejciac781922015-07-09 15:35:14 +0200316 if (type->der->type.der && type->info.bits.count) {
317 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100318 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200319 goto error;
320 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200321
322 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100323 if (!type->info.bits.bit) {
324 LOGMEM;
325 goto error;
326 }
Radek Krejci73adb602015-07-02 18:07:40 +0200327 p = 0;
328 i = -1;
329 LY_TREE_FOR(yin->child, next) {
330 i++;
331
332 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100333 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100334 goto error;
335 }
336
Radek Krejci994b6f62015-06-18 16:47:27 +0200337 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200338 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200339 type->info.bits.count = i + 1;
340 goto error;
341 }
342
343 /* check the name uniqueness */
344 for (j = 0; j < i; j++) {
345 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100346 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200347 type->info.bits.count = i + 1;
348 goto error;
349 }
350 }
351
Radek Krejci0d70c372015-07-02 16:23:10 +0200352 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200353 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200354 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
355 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200356 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200357 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200358
Radek Krejci0d70c372015-07-02 16:23:10 +0200359 if (!strcmp(node->name, "position")) {
360 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200361 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200362
363 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200364 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100365 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200366 type->info.bits.count = i + 1;
367 goto error;
368 }
369 type->info.bits.bit[i].pos = (uint32_t)p_;
370
371 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200372 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200373 p = type->info.bits.bit[i].pos;
374 p++;
375 } else {
376 /* check that the value is unique */
377 for (j = 0; j < i; j++) {
378 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100379 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100380 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200381 type->info.bits.count = i + 1;
382 goto error;
383 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200384 }
385 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200386 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100387 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200388 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200389 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200390 }
391 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200392 /* assign value automatically */
393 if (p > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100394 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200395 type->info.bits.count = i + 1;
396 goto error;
397 }
398 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100399 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200400 p++;
401 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200402
403 /* keep them ordered by position */
404 j = i;
405 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
406 /* switch them */
407 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
408 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
409 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
410 j--;
411 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200412 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200413 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200415 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200416 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200417 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200418 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
419 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200420 continue;
421 }
422
Radek Krejcif9401c32015-06-26 16:47:36 +0200423 if (!strcmp(node->name, "range")) {
424 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100425 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200426 goto error;
427 }
428
429 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200430 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100431 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200432 goto error;
433 }
434 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100435 if (!type->info.dec64.range) {
436 LOGMEM;
437 goto error;
438 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200439 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
440
441 /* get possible substatements */
442 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
443 goto error;
444 }
445 } else if (!strcmp(node->name, "fraction-digits")) {
446 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200448 goto error;
449 }
450 GETVAL(value, node, "value");
451 v = strtol(value, NULL, 10);
452
453 /* range check */
454 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100455 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200456 goto error;
457 }
458 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200459 type->info.dec64.div = 10;
460 for (i = 1; i < v; i++) {
461 type->info.dec64.div *= 10;
462 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200463 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100464 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200465 goto error;
466 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200467 }
468
469 /* mandatory sub-statement(s) check */
470 if (!type->info.dec64.dig && !type->der->type.der) {
471 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100472 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200473 goto error;
474 }
Radek Krejci7511f402015-07-10 09:56:30 +0200475 if (type->info.dec64.dig && type->der->type.der) {
476 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100477 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200478 goto error;
479 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200480 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200483 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200484
Radek Krejci994b6f62015-06-18 16:47:27 +0200485 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200486 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200487 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
488 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100489 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200490 continue;
491 }
492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200493 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200495 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100496 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200497 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200498 }
499 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200500 if (!type->der->type.der && !type->info.enums.count) {
501 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100502 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200503 goto error;
504 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200505 if (type->der->type.der && type->info.enums.count) {
506 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100507 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200508 goto error;
509 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200510
Radek Krejci1574a8d2015-08-03 14:16:52 +0200511 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100512 if (!type->info.enums.enm) {
513 LOGMEM;
514 goto error;
515 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200516
517 val_set = v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200518 i = -1;
519 LY_TREE_FOR(yin->child, next) {
520 i++;
521
522 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100523 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100524 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
525 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100526 goto error;
527 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200528 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200529 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 type->info.enums.count = i + 1;
531 goto error;
532 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200534 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200535 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200536 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100537 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200538 type->info.enums.count = i + 1;
539 goto error;
540 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200542 /* check the name uniqueness */
543 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200544 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100545 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200546 type->info.enums.count = i + 1;
547 goto error;
548 }
549 }
Radek Krejci04581c62015-05-22 21:24:00 +0200550
Radek Krejci73adb602015-07-02 18:07:40 +0200551 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200552 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
553 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200554 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200555 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200556
Radek Krejci0d70c372015-07-02 16:23:10 +0200557 if (!strcmp(node->name, "value")) {
558 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200559 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200560
561 /* range check */
562 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100563 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200564 type->info.enums.count = i + 1;
565 goto error;
566 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200567 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200568
569 /* keep the highest enum value for automatic increment */
Radek Krejcifc8d8322016-06-24 11:23:23 +0200570 if (!val_set || type->info.enums.enm[i].value > v) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200571 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200572 v++;
573 } else {
574 /* check that the value is unique */
575 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200576 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100577 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100578 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200579 type->info.enums.count = i + 1;
580 goto error;
581 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200582 }
583 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200584 val_set = 1;
Radek Krejci0d70c372015-07-02 16:23:10 +0200585 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100586 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200587 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200588 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200589 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200590 if (!val_set) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 /* assign value automatically */
592 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100593 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 type->info.enums.count = i + 1;
595 goto error;
596 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200597 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100598 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599 v++;
600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200601 }
602 break;
603
604 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200605 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200606
607 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200608 LY_TREE_FOR_SAFE(yin->child, next, node) {
609 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
610 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100611 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200612 continue;
613 }
614
Michal Vaskoe29c6622015-11-27 15:02:31 +0100615 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100616 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200617 goto error;
618 }
619 }
620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200622 if (type->der->type.der) {
623 /* this is just a derived type with no base specified/required */
624 break;
625 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100626 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200627 goto error;
628 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100630 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200631 goto error;
632 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200633 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100634 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100635 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100636 if (!value) {
637 goto error;
638 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100639 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100640 lydict_remove(module->ctx, value);
641
642 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200643 goto error;
644 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200645 break;
646
647 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200648 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200649 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200650 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
651 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200652 continue;
653 }
654
Radek Krejciaf351422015-06-19 14:49:38 +0200655 if (!strcmp(node->name, "require-instance")) {
656 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100657 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200658 goto error;
659 }
660 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200661 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200662 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200663 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200664 type->info.inst.req = -1;
665 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100666 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200667 goto error;
668 }
669 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100670 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200671 goto error;
672 }
Radek Krejciaf351422015-06-19 14:49:38 +0200673 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200675 break;
676
Radek Krejcif2860132015-06-20 12:37:20 +0200677 case LY_TYPE_BINARY:
678 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 case LY_TYPE_INT8:
680 case LY_TYPE_INT16:
681 case LY_TYPE_INT32:
682 case LY_TYPE_INT64:
683 case LY_TYPE_UINT8:
684 case LY_TYPE_UINT16:
685 case LY_TYPE_UINT32:
686 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200687 /* RFC 6020 9.2.4 - range */
688
689 /* length and range are actually the same restriction, so process
690 * them by this common code, we just need to differ the name and
691 * structure where the information will be stored
692 */
693 if (type->base == LY_TYPE_BINARY) {
694 restr = &type->info.binary.length;
695 name = "length";
696 } else {
697 restr = &type->info.num.range;
698 name = "range";
699 }
700
Radek Krejci73adb602015-07-02 18:07:40 +0200701 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200702 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
703 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200704 continue;
705 }
706
Radek Krejcif2860132015-06-20 12:37:20 +0200707 if (!strcmp(node->name, name)) {
708 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100709 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200710 goto error;
711 }
712
713 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200714 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100715 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200716 goto error;
717 }
718 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100719 if (!(*restr)) {
720 LOGMEM;
721 goto error;
722 }
Radek Krejcif2860132015-06-20 12:37:20 +0200723 (*restr)->expr = lydict_insert(module->ctx, value, 0);
724
725 /* get possible substatements */
726 if (read_restr_substmt(module->ctx, *restr, node)) {
727 goto error;
728 }
729 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100730 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200731 goto error;
732 }
Radek Krejcif2860132015-06-20 12:37:20 +0200733 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200734 break;
735
736 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200737 /* flag resolving for later use */
738 if (!tpdftype) {
739 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
740 if (siter) {
741 /* just a flag - do not resolve */
742 tpdftype = 1;
743 }
744 }
745
Radek Krejcidc4c1412015-06-19 15:39:54 +0200746 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200747 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200748 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
749 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200750 continue;
751 }
752
Michal Vasko88c29542015-11-27 14:57:53 +0100753 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200754 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100755 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200756 goto error;
757 }
758
759 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200760 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100761 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200762 if (!type->info.lref.path) {
763 goto error;
764 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200765
766 /* try to resolve leafref path only when this is instantiated
767 * leaf, so it is not:
768 * - typedef's type,
769 * - in grouping definition,
770 * - just instantiated in a grouping definition,
771 * because in those cases the nodes referenced in path might not be present
772 * and it is not a bug. */
773 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200774 goto error;
775 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200776
Radek Krejcidc4c1412015-06-19 15:39:54 +0200777 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100778 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200779 goto error;
780 }
Radek Krejci73adb602015-07-02 18:07:40 +0200781 }
782
Radek Krejci742be352016-07-17 12:18:54 +0200783 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +0200784 if (!type->der->type.der) {
785 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Michal Vasko01c6fd22016-05-20 11:43:05 +0200786 goto error;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200787 } else {
788 /* copy leafref definition into the derived type */
789 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
790 /* and resolve the path at the place we are (if not in grouping/typedef) */
791 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
792 goto error;
793 }
794
795 /* add pointer to leafref target, only on leaves (not in typedefs) */
796 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
797 goto error;
798 }
Michal Vasko01c6fd22016-05-20 11:43:05 +0200799 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200800 }
Radek Krejci742be352016-07-17 12:18:54 +0200801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 break;
803
804 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200805 /* RFC 6020 9.4.4 - length */
806 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200807 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200808 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200809 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
810 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100811 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200812 continue;
813 }
814
Radek Krejci3733a802015-06-19 13:43:21 +0200815 if (!strcmp(node->name, "length")) {
816 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100817 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200818 goto error;
819 }
820
821 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200822 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100823 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200824 goto error;
825 }
826 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100827 if (!type->info.str.length) {
828 LOGMEM;
829 goto error;
830 }
Radek Krejci3733a802015-06-19 13:43:21 +0200831 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
832
Radek Krejci5fbc9162015-06-19 14:11:11 +0200833 /* get possible sub-statements */
834 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200835 goto error;
836 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100837 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200838 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200839 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200840 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100841 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200842 goto error;
843 }
844 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200845 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200846 if (i) {
847 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100848 if (!type->info.str.patterns) {
849 LOGMEM;
850 goto error;
851 }
Radek Krejci73adb602015-07-02 18:07:40 +0200852 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100853 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200854
Michal Vasko0aee5c12016-06-17 14:27:26 +0200855 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +0200856 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +0200857 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +0200858 goto error;
859 }
Michal Vasko69068852015-07-13 14:34:31 +0200860
Radek Krejci73adb602015-07-02 18:07:40 +0200861 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200862
863 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100864 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200865 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200866 goto error;
867 }
Radek Krejci73adb602015-07-02 18:07:40 +0200868 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200869 }
870 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200871 break;
872
873 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200874 /* RFC 6020 7.4 - type */
875 /* count number of types in union */
876 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200877 LY_TREE_FOR_SAFE(yin->child, next, node) {
878 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
879 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100880 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200881 continue;
882 }
883
Radek Krejcie4c366b2015-07-02 10:11:31 +0200884 if (!strcmp(node->name, "type")) {
885 i++;
886 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100887 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200888 goto error;
889 }
890 }
891
892 if (!i) {
893 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100894 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200895 break;
896 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100897 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200898 goto error;
899 }
900
901 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200902 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100903 if (!type->info.uni.types) {
904 LOGMEM;
905 goto error;
906 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200907 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200908 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100909 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200910 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +0100911 if (!rc) {
912 type->info.uni.count++;
913
914 /* union's type cannot be empty or leafref */
915 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100916 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100917 rc = -1;
918 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100919 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100920 rc = -1;
921 }
922 }
923 if (rc) {
924 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
925 for (i = 0; i < type->info.uni.count; ++i) {
926 lys_type_free(module->ctx, &type->info.uni.types[i]);
927 }
928 free(type->info.uni.types);
929 type->info.uni.types = NULL;
930 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +0200931 type->der = NULL;
932 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +0100933
934 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100935 ret = EXIT_FAILURE;
936 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100937 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200938 goto error;
939 }
Michal Vasko88c29542015-11-27 14:57:53 +0100940 }
941 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200942
Michal Vasko88c29542015-11-27 14:57:53 +0100943 case LY_TYPE_BOOL:
944 case LY_TYPE_EMPTY:
945 /* no sub-statement allowed */
946 LY_TREE_FOR(yin->child, node) {
947 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100948 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200949 goto error;
950 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200951 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 break;
953
954 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100955 LOGINT;
956 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 }
958
959 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200960
961error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100962 if (type->module_name) {
963 lydict_remove(module->ctx, type->module_name);
964 type->module_name = NULL;
965 }
966 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200967}
968
Michal Vasko0d343d12015-08-24 14:57:36 +0200969/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200971fill_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 +0200972{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100974 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100975 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200977 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100978 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 goto error;
980 }
981 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100984 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 goto error;
986 }
Radek Krejcieac35532015-05-31 19:09:15 +0200987
Michal Vasko88c29542015-11-27 14:57:53 +0100988 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200989 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
990 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 continue;
992 }
993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100995 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100996 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 goto error;
998 }
Michal Vasko88c29542015-11-27 14:57:53 +0100999 /* HACK for unres */
1000 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001001 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001002 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001003 goto error;
1004 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001005 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 } else if (!strcmp(node->name, "default")) {
1007 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001008 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 goto error;
1010 }
1011 GETVAL(value, node, "value");
1012 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1013 } else if (!strcmp(node->name, "units")) {
1014 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001015 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001016 goto error;
1017 }
1018 GETVAL(value, node, "name");
1019 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1020 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001021 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 goto error;
1023 }
1024 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001026 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001027 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001028 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001029 goto error;
1030 }
Radek Krejcieac35532015-05-31 19:09:15 +02001031
Michal Vasko478c4652016-07-21 12:55:01 +02001032 /* check default value (if not defined, there still could be some restrictions
1033 * that need to be checked against a default value from a derived type) */
1034 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
1035 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001038 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001039
1040error:
1041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001043}
1044
Michal Vasko0d343d12015-08-24 14:57:36 +02001045/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001046static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001047fill_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 +02001048{
1049 const char *value;
1050 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001051 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001052
Radek Krejcib05774c2015-06-18 13:52:59 +02001053 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001054 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001055 goto error;
1056 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001057 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001058 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001059
Radek Krejci76512572015-08-04 09:47:08 +02001060 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001061 goto error;
1062 }
1063
1064 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001065 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1066 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001067 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001068 continue;
1069 }
1070
Radek Krejci3cf9e222015-06-18 11:37:50 +02001071 if (!strcmp(child->name, "if-feature")) {
1072 c++;
1073 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001074 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001075 goto error;
1076 }
1077 }
1078
1079 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001080 f->iffeature = calloc(c, sizeof *f->iffeature);
1081 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001082 LOGMEM;
1083 goto error;
1084 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001085 }
Radek Krejci73adb602015-07-02 18:07:40 +02001086 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001087 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1088 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001089 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001090 goto error;
1091 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001092 }
1093
Radek Krejci3cf9e222015-06-18 11:37:50 +02001094 return EXIT_SUCCESS;
1095
1096error:
1097
1098 return EXIT_FAILURE;
1099}
1100
Michal Vasko0d343d12015-08-24 14:57:36 +02001101/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102static int
Radek Krejcib8048692015-08-05 13:36:34 +02001103fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001104{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001105 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001108 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001109 if (!must->expr) {
1110 goto error;
1111 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001112 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001113 goto error;
1114 }
Radek Krejci800af702015-06-02 13:46:01 +02001115
Radek Krejci41726f92015-06-19 13:11:05 +02001116 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001117
Michal Vasko77dc5652016-02-15 12:32:42 +01001118error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001120}
1121
Radek Krejci581ce772015-11-10 17:22:40 +01001122static int
Michal Vasko88c29542015-11-27 14:57:53 +01001123fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1124 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001125{
1126 int i, j;
1127 const char *value, *vaux;
1128
1129 /* get unique value (list of leafs supposed to be unique */
1130 GETVAL(value, yin, "tag");
1131
1132 /* count the number of unique leafs in the value */
1133 vaux = value;
1134 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001135 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001136 while (isspace(*vaux)) {
1137 vaux++;
1138 }
1139 }
1140 unique->expr_size++;
1141 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001142 if (!unique->expr) {
1143 LOGMEM;
1144 goto error;
1145 }
Radek Krejci581ce772015-11-10 17:22:40 +01001146
1147 for (i = 0; i < unique->expr_size; i++) {
1148 vaux = strpbrk(value, " \t\n");
1149 if (!vaux) {
1150 /* the last token, lydict_insert() will count its size on its own */
1151 vaux = value;
1152 }
1153
1154 /* store token into unique structure */
1155 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1156
1157 /* check that the expression does not repeat */
1158 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001159 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001160 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1161 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001162 goto error;
1163 }
1164 }
1165
1166 /* try to resolve leaf */
1167 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001168 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1169 goto error;
1170 }
Radek Krejci581ce772015-11-10 17:22:40 +01001171 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001172 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001173 goto error;
1174 }
1175 }
1176
1177 /* move to next token */
1178 value = vaux;
1179 while(isspace(*value)) {
1180 value++;
1181 }
1182 }
1183
1184 return EXIT_SUCCESS;
1185
1186error:
1187 return EXIT_FAILURE;
1188}
1189
Michal Vasko0d343d12015-08-24 14:57:36 +02001190/* logs directly
1191 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001192 * type: 0 - min, 1 - max
1193 */
1194static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001195deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001196{
1197 const char *value;
1198 char *endptr;
1199 unsigned long val;
1200 uint32_t *ui32val;
1201
Michal Vaskof7e57d52016-03-07 11:31:09 +01001202 /* del min/max is forbidden */
1203 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001204 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001205 goto error;
1206 }
1207
Radek Krejcieb00f512015-07-01 16:44:58 +02001208 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001209 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001210 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001211 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001212 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001213 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001214 }
Radek Krejci76512572015-08-04 09:47:08 +02001215 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001216 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001217 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001218 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001219 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001220 }
1221 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001222 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1223 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001224 goto error;
1225 }
1226
1227 GETVAL(value, node, "value");
1228 while (isspace(value[0])) {
1229 value++;
1230 }
1231
Radek Krejci0d7b2472016-02-12 11:11:03 +01001232 if (type && !strcmp(value, "unbounded")) {
1233 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001234 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001235 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001236 /* convert it to uint32_t */
1237 errno = 0;
1238 endptr = NULL;
1239 val = strtoul(value, &endptr, 10);
1240 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001241 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001242 goto error;
1243 }
1244 if (type) {
1245 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001246 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001247 } else {
1248 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001249 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001250 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001251 }
1252
1253 if (d->mod == LY_DEVIATE_ADD) {
1254 /* check that there is no current value */
1255 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001256 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1257 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001258 goto error;
1259 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001260 } else if (d->mod == LY_DEVIATE_RPL) {
1261 /* unfortunately, there is no way to check reliably that there
1262 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001263 }
1264
Michal Vaskof7e57d52016-03-07 11:31:09 +01001265 /* add (already checked) and replace */
1266 /* set new value specified in deviation */
1267 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001268
1269 return EXIT_SUCCESS;
1270
1271error:
1272
1273 return EXIT_FAILURE;
1274}
1275
Michal Vasko0d343d12015-08-24 14:57:36 +02001276/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001277static int
Michal Vasko88c29542015-11-27 14:57:53 +01001278fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1279 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001280{
1281 const char *value, **stritem;
1282 struct lyxml_elem *next, *child, *develem;
1283 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001284 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001285 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001286 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001287 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001288 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001289 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001290 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001291 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001292 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001293 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001294 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001295 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001296
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001297 ctx = module->ctx;
1298
Radek Krejcieb00f512015-07-01 16:44:58 +02001299 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001300 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001301 if (!dev->target_name) {
1302 goto error;
1303 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001304
1305 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001306 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1307 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001308 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001309 goto error;
1310 }
Radek Krejcic4283442016-04-22 09:19:27 +02001311 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001312 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1313 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001314 goto error;
1315 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001316 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001317
1318 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001319 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1320 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001321 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001322 continue;
1323 }
1324
Radek Krejcieb00f512015-07-01 16:44:58 +02001325 if (!strcmp(child->name, "description")) {
1326 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001327 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001328 goto error;
1329 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001330 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001331 if (!dev->dsc) {
1332 goto error;
1333 }
1334 } else if (!strcmp(child->name, "reference")) {
1335 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001336 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001337 goto error;
1338 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001339 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001340 if (!dev->ref) {
1341 goto error;
1342 }
1343 } else if (!strcmp(child->name, "deviate")) {
1344 c_dev++;
1345
Michal Vasko345da0a2015-12-02 10:35:55 +01001346 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001347 * further processed later
1348 */
1349 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001350
Radek Krejcieb00f512015-07-01 16:44:58 +02001351 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001352 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001353 goto error;
1354 }
1355
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001356 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001357 }
1358
1359 if (c_dev) {
1360 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001361 if (!dev->deviate) {
1362 LOGMEM;
1363 goto error;
1364 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001365 }
1366
1367 LY_TREE_FOR(yin->child, develem) {
1368 /* init */
1369 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001370 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001371 c_must = 0;
1372 c_uniq = 0;
1373
1374 /* get deviation type */
1375 GETVAL(value, develem, "value");
1376 if (!strcmp(value, "not-supported")) {
1377 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1378 /* no property expected in this case */
1379 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001380 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001381 goto error;
1382 }
1383
Radek Krejci5b917642015-07-02 09:03:13 +02001384 /* and neither any other deviate statement is expected,
1385 * not-supported deviation must be the only deviation of the target
1386 */
1387 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001388 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1389 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001390 goto error;
1391 }
1392
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001393 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001394 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1395 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1396 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001397 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1398 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001399 goto error;
1400 }
1401 }
1402 }
Radek Krejci5b917642015-07-02 09:03:13 +02001403
Michal Vaskoff006c12016-02-17 11:15:19 +01001404 /* unlink and store the original node */
1405 lys_node_unlink(dev_target);
1406 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001407
Radek Krejci5b917642015-07-02 09:03:13 +02001408 dev->deviate_size = 1;
1409 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001410 } else if (!strcmp(value, "add")) {
1411 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1412 } else if (!strcmp(value, "replace")) {
1413 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1414 } else if (!strcmp(value, "delete")) {
1415 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1416 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001417 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 goto error;
1419 }
1420 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001421 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001422
Michal Vaskoff006c12016-02-17 11:15:19 +01001423 /* store a shallow copy of the original node */
1424 if (!dev->orig_node) {
1425 memset(&tmp_unres, 0, sizeof tmp_unres);
1426 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1427 /* just to be safe */
1428 if (tmp_unres.count) {
1429 LOGINT;
1430 goto error;
1431 }
1432 }
1433
Radek Krejcieb00f512015-07-01 16:44:58 +02001434 /* process deviation properties */
1435 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001436 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1437 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001438 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001439 continue;
1440 }
1441
Radek Krejcieb00f512015-07-01 16:44:58 +02001442 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001443 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001444 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001445 goto error;
1446 }
1447
1448 /* for we deviate from RFC 6020 and allow config property even it is/is not
1449 * specified in the target explicitly since config property inherits. So we expect
1450 * that config is specified in every node. But for delete, we check that the value
1451 * is the same as here in deviation
1452 */
1453 GETVAL(value, child, "value");
1454 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001455 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001456 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001457 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001458 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001459 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001460 goto error;
1461 }
1462
1463 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001464 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001465 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001466 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001467 } else { /* add and replace are the same in this case */
1468 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001469 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001470
1471 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001472 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001473 }
1474 } else if (!strcmp(child->name, "default")) {
1475 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001476 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001477 goto error;
1478 }
1479 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001480 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001481
Michal Vasko60f4b452016-02-12 11:02:55 +01001482 if (dev_target->nodetype == LYS_CHOICE) {
1483 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001484
1485 if (d->mod == LY_DEVIATE_ADD) {
1486 /* check that there is no current value */
1487 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001488 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1489 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001490 goto error;
1491 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001492 /* check collision with mandatory */
1493 if (choice->flags & LYS_MAND_TRUE) {
1494 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1495 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1496 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1497 goto error;
1498 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001499 } else if (d->mod == LY_DEVIATE_RPL) {
1500 /* check that there was a value before */
1501 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001502 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1503 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001504 goto error;
1505 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001506 }
1507
Michal Vasko3edeaf72016-02-11 13:17:43 +01001508 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001509 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001510 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001511 goto error;
1512 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001514 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001515 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1516 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001517 goto error;
1518 }
1519 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001520 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001521 if (!choice->dflt) {
1522 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001523 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001524 goto error;
1525 }
1526 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001527 } else if (dev_target->nodetype == LYS_LEAF) {
1528 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001529
1530 if (d->mod == LY_DEVIATE_ADD) {
1531 /* check that there is no current value */
1532 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001533 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1534 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001535 goto error;
1536 }
Radek Krejci841ec082016-04-05 13:05:17 +02001537 /* check collision with mandatory */
1538 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001539 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001540 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001541 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001542 goto error;
1543 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 }
1545
1546 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001547 if (!leaf->dflt || !ly_strequal(leaf->dflt, d->dflt, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001548 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1549 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 goto error;
1551 }
1552 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001553 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 leaf->dflt = NULL;
1555 } else { /* add (already checked) and replace */
1556 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001557 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001558
1559 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001560 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001561
1562 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1563 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1564 if (!leaf_dflt_check) {
1565 LOGMEM;
1566 goto error;
1567 }
1568 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001569 }
1570 } else {
1571 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001572 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1573 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001574 goto error;
1575 }
1576 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001577 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001578 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001579 goto error;
1580 }
1581
1582 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001583 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001584 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1585 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001586 goto error;
1587 }
1588
1589 GETVAL(value, child, "value");
1590 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001591 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001592 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001593 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001594 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001595 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001596 goto error;
1597 }
1598
1599 if (d->mod == LY_DEVIATE_ADD) {
1600 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001601 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001602 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1603 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001604 goto error;
1605 }
Radek Krejci841ec082016-04-05 13:05:17 +02001606 /* check collision with default-stmt */
1607 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001608 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001609 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001610 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001611 goto error;
1612 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001613
Michal Vasko21be1b32016-03-07 12:31:34 +01001614 dev_target->flags |= d->flags & LYS_MAND_MASK;
1615 } else if (d->mod == LY_DEVIATE_RPL) {
1616 /* check that there was a value before */
1617 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001618 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1619 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001620 goto error;
1621 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001622
Michal Vasko21be1b32016-03-07 12:31:34 +01001623 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001624 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001625 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001626 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001627 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001628 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001629 }
1630 } else if (!strcmp(child->name, "min-elements")) {
1631 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001632 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001633 goto error;
1634 }
1635 f_min = 1;
1636
Michal Vasko60f4b452016-02-12 11:02:55 +01001637 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 goto error;
1639 }
1640 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001641 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001642 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001643 goto error;
1644 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001645 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001646
Michal Vasko60f4b452016-02-12 11:02:55 +01001647 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001648 goto error;
1649 }
1650 } else if (!strcmp(child->name, "must")) {
1651 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001652 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 continue;
1654 } else if (!strcmp(child->name, "type")) {
1655 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001656 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001657 goto error;
1658 }
1659
Michal Vaskof7e57d52016-03-07 11:31:09 +01001660 /* add, del type is forbidden */
1661 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001662 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001663 goto error;
1664 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001665 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001666 goto error;
1667 }
1668
Radek Krejcieb00f512015-07-01 16:44:58 +02001669 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001670 if (dev_target->nodetype == LYS_LEAF) {
1671 t = &((struct lys_node_leaf *)dev_target)->type;
1672 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1673 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001674 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001675 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1676 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001677 goto error;
1678 }
1679
Radek Krejcieb00f512015-07-01 16:44:58 +02001680 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001681 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001682 /* HACK for unres */
1683 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001684 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001685 goto error;
1686 }
1687 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001688
1689 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1690 if (dev_target->nodetype == LYS_LEAF) {
1691 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1692 if (!leaf_dflt_check) {
1693 LOGMEM;
1694 goto error;
1695 }
1696 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1697 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001698 } else if (!strcmp(child->name, "unique")) {
1699 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001700 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001701 continue;
1702 } else if (!strcmp(child->name, "units")) {
1703 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001704 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001705 goto error;
1706 }
1707
1708 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001709 if (dev_target->nodetype == LYS_LEAFLIST) {
1710 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1711 } else if (dev_target->nodetype == LYS_LEAF) {
1712 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001714 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1715 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 goto error;
1717 }
1718
1719 /* get units value */
1720 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001721 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001722
1723 /* apply to target */
1724 if (d->mod == LY_DEVIATE_ADD) {
1725 /* check that there is no current value */
1726 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001727 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1728 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 goto error;
1730 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001731
Michal Vasko21be1b32016-03-07 12:31:34 +01001732 *stritem = lydict_insert(ctx, value, 0);
1733 } else if (d->mod == LY_DEVIATE_RPL) {
1734 /* check that there was a value before */
1735 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001736 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1737 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001738 goto error;
1739 }
1740
1741 lydict_remove(ctx, *stritem);
1742 *stritem = lydict_insert(ctx, value, 0);
1743 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001744 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001745 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001746 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1747 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001748 goto error;
1749 }
1750 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001751 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001752 }
1753 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001754 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001755 goto error;
1756 }
1757
Michal Vasko88c29542015-11-27 14:57:53 +01001758 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001759 }
1760
1761 if (c_must) {
1762 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001763 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001764 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001765 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1766 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001767 break;
Radek Krejci76512572015-08-04 09:47:08 +02001768 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001769 trg_must = &((struct lys_node_container *)dev_target)->must;
1770 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 break;
Radek Krejci76512572015-08-04 09:47:08 +02001772 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001773 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1774 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001775 break;
Radek Krejci76512572015-08-04 09:47:08 +02001776 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001777 trg_must = &((struct lys_node_list *)dev_target)->must;
1778 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 break;
Radek Krejci76512572015-08-04 09:47:08 +02001780 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001781 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1782 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001783 break;
1784 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001785 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1786 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001787 goto error;
1788 }
1789
1790 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001791 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001792 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001793 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001794 } else if (d->mod == LY_DEVIATE_ADD) {
1795 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001796 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001797 if (!d->must) {
1798 LOGMEM;
1799 goto error;
1800 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001802 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001803 d->must_size = c_must;
1804 } else { /* LY_DEVIATE_DEL */
1805 d->must = calloc(c_must, sizeof *d->must);
1806 }
Michal Vasko253035f2015-12-17 16:58:13 +01001807 if (!d->must) {
1808 LOGMEM;
1809 goto error;
1810 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 }
1812 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001813 /* replace unique is forbidden */
1814 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001815 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001816 goto error;
1817 }
1818
Radek Krejcieb00f512015-07-01 16:44:58 +02001819 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001820 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001821 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1822 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 goto error;
1824 }
1825
Michal Vasko60f4b452016-02-12 11:02:55 +01001826 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001827 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001828 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001829 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001830 list->unique = d->unique;
1831 d->unique = &list->unique[list->unique_size];
1832 d->unique_size = c_uniq;
1833 } else { /* LY_DEVIATE_DEL */
1834 d->unique = calloc(c_uniq, sizeof *d->unique);
1835 }
Michal Vasko253035f2015-12-17 16:58:13 +01001836 if (!d->unique) {
1837 LOGMEM;
1838 goto error;
1839 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001840 }
1841
1842 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001843 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 if (!strcmp(child->name, "must")) {
1845 if (d->mod == LY_DEVIATE_DEL) {
1846 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1847 goto error;
1848 }
1849
1850 /* find must to delete, we are ok with just matching conditions */
1851 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001852 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001853 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001854 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 /* ... and maintain the array */
1856 (*trg_must_size)--;
1857 if (i != *trg_must_size) {
1858 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1859 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1860 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1861 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1862 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1863 }
1864 if (!(*trg_must_size)) {
1865 free(*trg_must);
1866 *trg_must = NULL;
1867 } else {
1868 (*trg_must)[*trg_must_size].expr = NULL;
1869 (*trg_must)[*trg_must_size].dsc = NULL;
1870 (*trg_must)[*trg_must_size].ref = NULL;
1871 (*trg_must)[*trg_must_size].eapptag = NULL;
1872 (*trg_must)[*trg_must_size].emsg = NULL;
1873 }
1874
1875 i = -1; /* set match flag */
1876 break;
1877 }
1878 }
1879 d->must_size++;
1880 if (i != -1) {
1881 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001882 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001883 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001884 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001885 goto error;
1886 }
1887 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001888 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1889 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001890 goto error;
1891 }
1892 (*trg_must_size)++;
1893 }
1894 } else if (!strcmp(child->name, "unique")) {
1895 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001896 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001897 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001898 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001899 goto error;
1900 }
1901
1902 /* find unique structures to delete */
1903 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001904 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001905 continue;
1906 }
1907
Radek Krejci581ce772015-11-10 17:22:40 +01001908 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001909 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 break;
1911 }
1912 }
1913
Radek Krejci581ce772015-11-10 17:22:40 +01001914 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001915 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001916 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001917 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001918 }
1919 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001920 /* ... and maintain the array */
1921 list->unique_size--;
1922 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001923 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1924 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001925 }
1926
1927 if (!list->unique_size) {
1928 free(list->unique);
1929 list->unique = NULL;
1930 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001931 list->unique[list->unique_size].expr_size = 0;
1932 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001933 }
1934
1935 i = -1; /* set match flag */
1936 break;
1937 }
1938 }
1939
1940 d->unique_size++;
1941 if (i != -1) {
1942 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001943 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1944 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001945 goto error;
1946 }
1947 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001948 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001949 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001950 list->unique_size++;
1951 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001952 goto error;
1953 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001954 }
1955 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001956 }
1957 }
1958
Michal Vasko43a1feb2016-03-07 12:03:02 +01001959 /* now check whether default value, if any, matches the type */
1960 for (i = 0; i < leaf_dflt_check_count; ++i) {
1961 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001962 rc = unres_schema_add_str(module, unres, &leaf_dflt_check[i]->type, UNRES_TYPE_DFLT, leaf_dflt_check[i]->dflt);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001963 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001964 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1965 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->target_name);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001966 goto error;
1967 }
1968 }
1969 }
1970 free(leaf_dflt_check);
1971
Radek Krejcieb00f512015-07-01 16:44:58 +02001972 return EXIT_SUCCESS;
1973
1974error:
Michal Vasko34867132016-03-11 10:26:38 +01001975 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001976 return EXIT_FAILURE;
1977}
1978
Michal Vasko0d343d12015-08-24 14:57:36 +02001979/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001980static int
Radek Krejcib8048692015-08-05 13:36:34 +02001981fill_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 +02001982 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001983{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001985 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001986 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001987 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001988
Michal Vasko591e0b22015-08-13 13:53:43 +02001989 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001991 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02001992 if (!aug->target_name) {
1993 goto error;
1994 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001996
Michal Vasko1d87a922015-08-21 12:57:16 +02001997 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001998 goto error;
1999 }
2000
2001 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002002 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2003 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002004 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002005 continue;
2006 }
2007
Radek Krejci3cf9e222015-06-18 11:37:50 +02002008 if (!strcmp(child->name, "if-feature")) {
2009 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002010 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002011 } else if (!strcmp(child->name, "when")) {
2012 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002013 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002014 goto error;
2015 }
2016
2017 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002018 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002019 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002020 goto error;
2021 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002022 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002024
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 /* check allowed data sub-statements */
2026 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002028 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002029 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002030 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002031 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002032 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002033 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002034 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002035 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002036 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002037 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002038 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002039 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002040 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002041 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002042 } else if (!strcmp(child->name, "action")) {
2043 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002044 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002045 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002046 goto error;
2047 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002048
Radek Krejci1d82ef62015-08-07 14:44:40 +02002049 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002050 goto error;
2051 }
2052
Radek Krejci1d82ef62015-08-07 14:44:40 +02002053 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002054 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002055 }
2056
2057 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002058 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2059 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002060 LOGMEM;
2061 goto error;
2062 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002063 }
2064
2065 LY_TREE_FOR_SAFE(yin->child, next, child) {
2066 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002067 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2068 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002069 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002070 goto error;
2071 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002072 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002073 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002074 }
2075
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002076 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002077 * connected to the tree and adjusted (if possible right now).
2078 * However, if this is augment in a uses, it gets resolved
2079 * when the uses does and cannot be resolved now for sure
2080 * (the grouping was not yet copied into uses).
2081 */
2082 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002083 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002084 goto error;
2085 }
Michal Vasko49291b32015-08-06 09:49:41 +02002086 }
Radek Krejci106efc02015-06-10 14:36:27 +02002087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002089
2090error:
2091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002093}
2094
Michal Vasko0d343d12015-08-24 14:57:36 +02002095/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096static int
Michal Vasko0d204592015-10-07 09:50:04 +02002097fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002098{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 struct lyxml_elem *sub, *next;
2100 const char *value;
2101 char *endptr;
2102 int f_mand = 0, f_min = 0, f_max = 0;
2103 int c_must = 0;
2104 int r;
2105 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002106
Radek Krejci76512572015-08-04 09:47:08 +02002107 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 goto error;
2109 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002110
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002111 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002112 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002113 if (!rfn->target_name) {
2114 goto error;
2115 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002118 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2119 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002120 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002121 continue;
2122 }
2123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 /* limited applicability */
2125 if (!strcmp(sub->name, "default")) {
2126 /* leaf or choice */
2127 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002128 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 goto error;
2130 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 /* check possibility of statements combination */
2133 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002134 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002136 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2137 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 goto error;
2139 }
2140 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002141 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 GETVAL(value, sub, "value");
2145 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2146 } else if (!strcmp(sub->name, "mandatory")) {
2147 /* leaf, choice or anyxml */
2148 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002149 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 goto error;
2151 }
2152 /* just checking the flags in leaf is not sufficient, we would allow
2153 * multiple mandatory statements with the "false" value
2154 */
2155 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 /* check possibility of statements combination */
2158 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002159 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002161 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2162 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 goto error;
2164 }
2165 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002166 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 GETVAL(value, sub, "value");
2170 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002171 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002173 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002175 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 goto error;
2177 }
2178 } else if (!strcmp(sub->name, "min-elements")) {
2179 /* list or leaf-list */
2180 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002181 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 goto error;
2183 }
2184 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 /* check possibility of statements combination */
2187 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002188 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002190 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2191 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 goto error;
2193 }
2194 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002195 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 GETVAL(value, sub, "value");
2199 while (isspace(value[0])) {
2200 value++;
2201 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 /* convert it to uint32_t */
2204 errno = 0;
2205 endptr = NULL;
2206 val = strtoul(value, &endptr, 10);
2207 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002208 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 goto error;
2210 }
2211 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002212 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 } else if (!strcmp(sub->name, "max-elements")) {
2214 /* list or leaf-list */
2215 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002216 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 goto error;
2218 }
2219 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 /* check possibility of statements combination */
2222 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002223 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002225 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2226 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 goto error;
2228 }
2229 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002230 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 GETVAL(value, sub, "value");
2234 while (isspace(value[0])) {
2235 value++;
2236 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002237
Radek Krejci0d7b2472016-02-12 11:11:03 +01002238 if (!strcmp(value, "unbounded")) {
2239 rfn->mod.list.max = 0;
2240 } else {
2241 /* convert it to uint32_t */
2242 errno = 0;
2243 endptr = NULL;
2244 val = strtoul(value, &endptr, 10);
2245 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002246 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002247 goto error;
2248 }
2249 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002251 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 } else if (!strcmp(sub->name, "presence")) {
2253 /* container */
2254 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002255 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 goto error;
2257 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 /* check possibility of statements combination */
2260 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002261 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002263 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2264 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 goto error;
2266 }
2267 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002268 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 GETVAL(value, sub, "value");
2272 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2273 } else if (!strcmp(sub->name, "must")) {
2274 /* leaf-list, list, container or anyxml */
2275 /* check possibility of statements combination */
2276 if (rfn->target_type) {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002277 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002279 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2280 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 goto error;
2282 }
2283 } else {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002284 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002288 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002291 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 goto error;
2293 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002294
Michal Vasko345da0a2015-12-02 10:35:55 +01002295 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 /* process nodes with cardinality of 0..n */
2299 if (c_must) {
2300 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002301 if (!rfn->must) {
2302 LOGMEM;
2303 goto error;
2304 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 }
Radek Krejci73adb602015-07-02 18:07:40 +02002306 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002307 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2308 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002309 if (r) {
2310 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002315
2316error:
2317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002319}
2320
Michal Vasko0d343d12015-08-24 14:57:36 +02002321/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322static int
Radek Krejcib8048692015-08-05 13:36:34 +02002323fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002324{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 struct lyxml_elem *child;
2326 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002329 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2330 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002331 continue;
2332 }
2333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 if (!strcmp(child->name, "prefix")) {
2335 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002336 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 goto error;
2338 }
2339 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2340 } else if (!strcmp(child->name, "revision-date")) {
2341 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002342 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2343 goto error;
2344 } else if (!imp->prefix) {
2345 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2346 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2347 "The \"prefix\" statement is expected before the \"revision-date\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 goto error;
2349 }
2350 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002351 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002352 goto error;
2353 }
2354 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2355 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002356 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 goto error;
2358 }
2359 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361 /* check mandatory information */
2362 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002363 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 goto error;
2365 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002368
Pavol Vicane994fda2016-03-22 10:47:58 +01002369 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002370
2371error:
2372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002374}
2375
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002376/* logs directly
2377 * returns:
2378 * 0 - inc successfully filled
2379 * -1 - error, inc is cleaned
2380 * 1 - duplication, ignore the inc structure, inc is cleaned
2381 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002382static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002383fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2384 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002385{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002386 struct lyxml_elem *child;
2387 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002390 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2391 /* garbage */
2392 continue;
2393 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 if (!strcmp(child->name, "revision-date")) {
2395 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002396 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 goto error;
2398 }
2399 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002400 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 goto error;
2402 }
2403 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2404 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002405 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 goto error;
2407 }
2408 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002411
Pavol Vican0adf01d2016-03-22 12:29:33 +01002412 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002413
2414error:
2415
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002416 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002417}
2418
Michal Vasko0d343d12015-08-24 14:57:36 +02002419/* logs directly
2420 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002421 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002422 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002423 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002424 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425static int
Radek Krejcib8048692015-08-05 13:36:34 +02002426read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002427 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002428{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 const char *value;
2430 struct lyxml_elem *sub, *next;
2431 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002434 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 if (opt & OPT_IDENT) {
2438 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002439 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002440 goto error;
2441 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002442 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002443 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002444
Radek Krejci6764bb32015-07-03 15:16:04 +02002445 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002446 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002447 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002448 }
2449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 /* process local parameters */
2451 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002452 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002453 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002454 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002455 continue;
2456 }
2457 if (strcmp(sub->ns->value, LY_NSYIN)) {
2458 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002459 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002460 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002461 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002462 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002463 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002464 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002465 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002466 goto error;
2467 }
2468 }
2469
2470 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002471 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002472 continue;
2473 }
2474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002476 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002477 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 goto error;
2479 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002480 node->dsc = read_yin_subnode(ctx, sub, "text");
2481 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002482 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 }
2484 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002486 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 goto error;
2488 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002489 node->ref = read_yin_subnode(ctx, sub, "text");
2490 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002491 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 }
2493 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002494 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002495 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 goto error;
2497 }
2498 GETVAL(value, sub, "value");
2499 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002500 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002502 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002504 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002506 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002507 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 }
2509 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002510 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002511 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002512 goto error;
2513 }
2514 GETVAL(value, sub, "value");
2515 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002516 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002517 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002518 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002519 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002520 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002521 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002522 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002523 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002525 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 continue;
2527 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002528 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002530
Radek Krejci1d82ef62015-08-07 14:44:40 +02002531 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002532 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002533 if (parent && (parent->flags & LYS_CONFIG_R)) {
2534 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 } else {
2536 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002537 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 }
2539 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002542
2543error:
2544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002546}
2547
Michal Vasko0d343d12015-08-24 14:57:36 +02002548/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002549static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002550read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002551{
Radek Krejci76512572015-08-04 09:47:08 +02002552 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002553 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002554 const char *value;
2555
2556 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002557 if (!retval) {
2558 LOGMEM;
2559 return NULL;
2560 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002561
2562 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002563 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002564 if (!retval->cond) {
2565 goto error;
2566 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002567 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002568 goto error;
2569 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002570
Radek Krejci73adb602015-07-02 18:07:40 +02002571 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002572 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2573 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002574 continue;
2575 }
2576
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002577 if (!strcmp(child->name, "description")) {
2578 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002579 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002580 goto error;
2581 }
2582 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2583 if (!retval->dsc) {
2584 goto error;
2585 }
2586 } else if (!strcmp(child->name, "reference")) {
2587 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002588 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002589 goto error;
2590 }
2591 retval->ref = read_yin_subnode(module->ctx, child, "text");
2592 if (!retval->ref) {
2593 goto error;
2594 }
2595 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002596 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002597 goto error;
2598 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002599 }
2600
2601 return retval;
2602
2603error:
2604
Michal Vasko0308dd62015-10-07 09:14:40 +02002605 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002606 return NULL;
2607}
2608
Michal Vasko0d343d12015-08-24 14:57:36 +02002609/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002610static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002611read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2612 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002613{
Michal Vasko29fc0182015-08-24 15:02:39 +02002614 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002615 struct lys_node_case *cs;
2616 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002617 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002618
Radek Krejcie867c852015-08-27 09:52:34 +02002619 /* init */
2620 memset(&root, 0, sizeof root);
2621
Radek Krejci1d82ef62015-08-07 14:44:40 +02002622 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002623 if (!cs) {
2624 LOGMEM;
2625 return NULL;
2626 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002627 cs->nodetype = LYS_CASE;
2628 cs->prev = (struct lys_node *)cs;
2629 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002630
Radek Krejci6a113852015-07-03 16:04:20 +02002631 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002632 goto error;
2633 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002634
Radek Krejcia9544502015-08-14 08:24:29 +02002635 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2636
Michal Vasko3a0043f2015-08-12 12:11:30 +02002637 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002638 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002639 goto error;
2640 }
2641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002642 /* process choice's specific children */
2643 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002644 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2645 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002646 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002647 continue;
2648 }
2649
Michal Vasko29fc0182015-08-24 15:02:39 +02002650 if (!strcmp(sub->name, "container") ||
2651 !strcmp(sub->name, "leaf-list") ||
2652 !strcmp(sub->name, "leaf") ||
2653 !strcmp(sub->name, "list") ||
2654 !strcmp(sub->name, "uses") ||
2655 !strcmp(sub->name, "choice") ||
2656 !strcmp(sub->name, "anyxml")) {
2657
Michal Vaskof3930de2015-10-22 12:03:59 +02002658 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002659 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002660 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002661 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002662 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002663 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002664 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002665 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002666 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002667 goto error;
2668 }
2669
Radek Krejci1d82ef62015-08-07 14:44:40 +02002670 cs->when = read_yin_when(module, sub);
2671 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002672 goto error;
2673 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002674
Michal Vasko345da0a2015-12-02 10:35:55 +01002675 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002676 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002677 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002681
Radek Krejci3cf9e222015-06-18 11:37:50 +02002682 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002683 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
2684 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002685 LOGMEM;
2686 goto error;
2687 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002688 }
Radek Krejci73adb602015-07-02 18:07:40 +02002689 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002690 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
2691 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002692 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002693 goto error;
2694 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 }
Radek Krejcib388c152015-06-04 17:03:03 +02002696
Michal Vasko29fc0182015-08-24 15:02:39 +02002697 /* last part - process data nodes */
2698 LY_TREE_FOR_SAFE(root.child, next, sub) {
2699 if (!strcmp(sub->name, "container")) {
2700 node = read_yin_container(module, retval, sub, resolve, unres);
2701 } else if (!strcmp(sub->name, "leaf-list")) {
2702 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2703 } else if (!strcmp(sub->name, "leaf")) {
2704 node = read_yin_leaf(module, retval, sub, resolve, unres);
2705 } else if (!strcmp(sub->name, "list")) {
2706 node = read_yin_list(module, retval, sub, resolve, unres);
2707 } else if (!strcmp(sub->name, "choice")) {
2708 node = read_yin_choice(module, retval, sub, resolve, unres);
2709 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002710 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02002711 } else if (!strcmp(sub->name, "anyxml")) {
2712 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2713 }
2714 if (!node) {
2715 goto error;
2716 }
2717
Michal Vasko345da0a2015-12-02 10:35:55 +01002718 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002719 }
2720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002722
2723error:
2724
Michal Vasko29fc0182015-08-24 15:02:39 +02002725 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002726 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002727 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002728 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002731}
2732
Michal Vasko0d343d12015-08-24 14:57:36 +02002733/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002734static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002735read_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 +02002736{
Radek Krejci629cdef2016-06-06 15:06:36 +02002737 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002739 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002740 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02002741 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02002742 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002744 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002745 if (!choice) {
2746 LOGMEM;
2747 return NULL;
2748 }
Radek Krejci76512572015-08-04 09:47:08 +02002749 choice->nodetype = LYS_CHOICE;
2750 choice->prev = (struct lys_node *)choice;
2751 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002752
Michal Vaskoe0c59842015-09-24 13:52:20 +02002753 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2754 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002755 goto error;
2756 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002757
Radek Krejcia9544502015-08-14 08:24:29 +02002758 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2759
Michal Vasko3a0043f2015-08-12 12:11:30 +02002760 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002761 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002762 goto error;
2763 }
2764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 /* process choice's specific children */
2766 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002767 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2768 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002769 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002770 continue;
2771 }
2772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002773 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002774 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002775 goto error;
2776 }
2777 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002778 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 goto error;
2780 }
2781 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002782 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 goto error;
2784 }
2785 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002786 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 goto error;
2788 }
2789 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002790 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002791 goto error;
2792 }
2793 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002794 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002795 goto error;
2796 }
2797 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02002798 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002799 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 goto error;
2801 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002802 dflt = sub;
2803 lyxml_unlink_elem(ctx, dflt, 0);
2804
Radek Krejcif9a312c2016-06-06 15:14:30 +02002805 continue;
2806 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
2807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002808 } else if (!strcmp(sub->name, "mandatory")) {
2809 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002810 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002811 goto error;
2812 }
2813 /* just checking the flags in leaf is not sufficient, we would allow
2814 * multiple mandatory statements with the "false" value
2815 */
2816 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 GETVAL(value, sub, "value");
2819 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002820 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002821 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002822 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002823 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002824 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 goto error;
2826 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002827 } else if (!strcmp(sub->name, "when")) {
2828 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002829 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002830 goto error;
2831 }
2832
2833 choice->when = read_yin_when(module, sub);
2834 if (!choice->when) {
2835 goto error;
2836 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002837 } else if (!strcmp(sub->name, "if-feature")) {
2838 c_ftrs++;
2839
Michal Vasko345da0a2015-12-02 10:35:55 +01002840 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002841 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002843 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002845 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002846
Radek Krejci1d82ef62015-08-07 14:44:40 +02002847 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002848 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002850
Radek Krejci3cf9e222015-06-18 11:37:50 +02002851 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002852 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
2853 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002854 LOGMEM;
2855 goto error;
2856 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002857 }
2858
Radek Krejci73adb602015-07-02 18:07:40 +02002859 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002860 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
2861 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002862 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002863 goto error;
2864 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002865 }
2866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002867 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02002868 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002869 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2870 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002871 goto error;
2872 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002874 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02002875 if (dflt) {
2876 GETVAL(value, dflt, "value");
2877 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002878 goto error;
2879 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002880 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002884
2885error:
2886
Radek Krejci629cdef2016-06-06 15:06:36 +02002887 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002888 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002891}
2892
Michal Vasko0d343d12015-08-24 14:57:36 +02002893/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002894static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002895read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002896 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002897{
Radek Krejci76512572015-08-04 09:47:08 +02002898 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002899 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002900 struct lyxml_elem *sub, *next;
2901 const char *value;
2902 int r;
2903 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002904 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002907 if (!anyxml) {
2908 LOGMEM;
2909 return NULL;
2910 }
Radek Krejci76512572015-08-04 09:47:08 +02002911 anyxml->nodetype = LYS_ANYXML;
2912 anyxml->prev = (struct lys_node *)anyxml;
2913 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002914
Michal Vaskoe0c59842015-09-24 13:52:20 +02002915 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2916 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 goto error;
2918 }
Radek Krejci863c2852015-06-03 15:47:11 +02002919
Radek Krejcia9544502015-08-14 08:24:29 +02002920 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002921
Radek Krejciadb30652016-07-11 15:27:07 +02002922 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002923 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002924 goto error;
2925 }
2926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002928 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2929 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002930 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002931 continue;
2932 }
2933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 if (!strcmp(sub->name, "mandatory")) {
2935 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002936 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 goto error;
2938 }
2939 /* just checking the flags in leaf is not sufficient, we would allow
2940 * multiple mandatory statements with the "false" value
2941 */
2942 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 GETVAL(value, sub, "value");
2945 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002946 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002947 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002948 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002949 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002950 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002951 goto error;
2952 }
2953 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002954 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002955 } else if (!strcmp(sub->name, "when")) {
2956 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002957 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002958 goto error;
2959 }
2960
2961 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002962 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002963 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002964 goto error;
2965 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002966 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 } else if (!strcmp(sub->name, "must")) {
2968 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002969 } else if (!strcmp(sub->name, "if-feature")) {
2970 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002972 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002973 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002974 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 }
2976 }
Radek Krejci863c2852015-06-03 15:47:11 +02002977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 /* middle part - process nodes with cardinality of 0..n */
2979 if (c_must) {
2980 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002981 if (!anyxml->must) {
2982 LOGMEM;
2983 goto error;
2984 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002986 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002987 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
2988 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002989 LOGMEM;
2990 goto error;
2991 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002992 }
Radek Krejci863c2852015-06-03 15:47:11 +02002993
Radek Krejci73adb602015-07-02 18:07:40 +02002994 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002995 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002996 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2997 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002998 if (r) {
2999 goto error;
3000 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003001 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003002 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3003 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003004 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003005 goto error;
3006 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 }
Radek Krejci863c2852015-06-03 15:47:11 +02003009
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003011
3012error:
3013
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003014 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003017}
3018
Michal Vasko0d343d12015-08-24 14:57:36 +02003019/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003020static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003021read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003022 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003023{
Radek Krejci76512572015-08-04 09:47:08 +02003024 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003025 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003026 struct lyxml_elem *sub, *next;
3027 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003028 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003029 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003032 if (!leaf) {
3033 LOGMEM;
3034 return NULL;
3035 }
Radek Krejci76512572015-08-04 09:47:08 +02003036 leaf->nodetype = LYS_LEAF;
3037 leaf->prev = (struct lys_node *)leaf;
3038 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003039
Michal Vaskoe0c59842015-09-24 13:52:20 +02003040 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3041 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 goto error;
3043 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003044
Radek Krejcia9544502015-08-14 08:24:29 +02003045 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003046
Radek Krejciadb30652016-07-11 15:27:07 +02003047 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003048 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003049 goto error;
3050 }
3051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003053 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3054 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003055 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003056 continue;
3057 }
3058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003060 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003061 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 goto error;
3063 }
Michal Vasko88c29542015-11-27 14:57:53 +01003064 /* HACK for unres */
3065 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003066 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko3767fb22016-07-21 12:10:57 +02003067 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003068 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 goto error;
3070 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003071 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 } else if (!strcmp(sub->name, "default")) {
3073 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003074 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 goto error;
3076 }
3077 GETVAL(value, sub, "value");
3078 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3079 } else if (!strcmp(sub->name, "units")) {
3080 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003081 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003082 goto error;
3083 }
3084 GETVAL(value, sub, "name");
3085 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3086 } else if (!strcmp(sub->name, "mandatory")) {
3087 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003088 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 goto error;
3090 }
3091 /* just checking the flags in leaf is not sufficient, we would allow
3092 * multiple mandatory statements with the "false" value
3093 */
3094 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 GETVAL(value, sub, "value");
3097 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003098 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003099 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003100 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003101 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003102 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003103 goto error;
3104 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003105 } else if (!strcmp(sub->name, "when")) {
3106 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003107 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003108 goto error;
3109 }
3110
3111 leaf->when = read_yin_when(module, sub);
3112 if (!leaf->when) {
3113 goto error;
3114 }
3115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003117 c_must++;
3118 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003119 } else if (!strcmp(sub->name, "if-feature")) {
3120 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003124 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003126 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003127
Michal Vasko88c29542015-11-27 14:57:53 +01003128 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003131 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003132 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003133 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003134 goto error;
3135 }
Michal Vasko478c4652016-07-21 12:55:01 +02003136 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3137 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3138 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3139 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3140 goto error;
3141 }
3142
3143 /* check default value (if not defined, there still could be some restrictions
3144 * that need to be checked against a default value from a derived type) */
3145 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3146 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003147 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 /* middle part - process nodes with cardinality of 0..n */
3150 if (c_must) {
3151 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003152 if (!leaf->must) {
3153 LOGMEM;
3154 goto error;
3155 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003157 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003158 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3159 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003160 LOGMEM;
3161 goto error;
3162 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003163 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003164
Radek Krejci73adb602015-07-02 18:07:40 +02003165 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003166 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003167 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3168 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 if (r) {
3170 goto error;
3171 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003172 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003173 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3174 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003175 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003176 goto error;
3177 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003182
3183error:
3184
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003185 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003188}
3189
Michal Vasko0d343d12015-08-24 14:57:36 +02003190/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003191static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003192read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003193 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003194{
Radek Krejci76512572015-08-04 09:47:08 +02003195 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003196 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 struct lyxml_elem *sub, *next;
3198 const char *value;
3199 char *endptr;
3200 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003201 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003202 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003206 if (!llist) {
3207 LOGMEM;
3208 return NULL;
3209 }
Radek Krejci76512572015-08-04 09:47:08 +02003210 llist->nodetype = LYS_LEAFLIST;
3211 llist->prev = (struct lys_node *)llist;
3212 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003213
Michal Vaskoe0c59842015-09-24 13:52:20 +02003214 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3215 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 goto error;
3217 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003218
Radek Krejcia9544502015-08-14 08:24:29 +02003219 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003220
Radek Krejciadb30652016-07-11 15:27:07 +02003221 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003222 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003223 goto error;
3224 }
3225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003226 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003227 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3228 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003229 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003230 continue;
3231 }
3232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003234 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003235 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003236 goto error;
3237 }
Michal Vasko88c29542015-11-27 14:57:53 +01003238 /* HACK for unres */
3239 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003240 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko3767fb22016-07-21 12:10:57 +02003241 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003242 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 goto error;
3244 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003245 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003246 } else if (!strcmp(sub->name, "units")) {
3247 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003248 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 goto error;
3250 }
3251 GETVAL(value, sub, "name");
3252 llist->units = lydict_insert(module->ctx, value, strlen(value));
3253 } else if (!strcmp(sub->name, "ordered-by")) {
3254 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003255 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 goto error;
3257 }
3258 /* just checking the flags in llist is not sufficient, we would
3259 * allow multiple ordered-by statements with the "system" value
3260 */
3261 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003262
Radek Krejci1574a8d2015-08-03 14:16:52 +02003263 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3265 * state data
3266 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003267 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 continue;
3269 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 GETVAL(value, sub, "value");
3272 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003273 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003275 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003276 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003277 } /* else system is the default value, so we can ignore it */
3278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 } else if (!strcmp(sub->name, "must")) {
3280 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003281 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003282 } else if (!strcmp(sub->name, "if-feature")) {
3283 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 } else if (!strcmp(sub->name, "min-elements")) {
3287 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003288 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 goto error;
3290 }
3291 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 GETVAL(value, sub, "value");
3294 while (isspace(value[0])) {
3295 value++;
3296 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 /* convert it to uint32_t */
3299 errno = 0;
3300 endptr = NULL;
3301 val = strtoul(value, &endptr, 10);
3302 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003303 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 goto error;
3305 }
3306 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003307 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003308 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3309 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003310 goto error;
3311 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 } else if (!strcmp(sub->name, "max-elements")) {
3313 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003314 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003315 goto error;
3316 }
3317 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 GETVAL(value, sub, "value");
3320 while (isspace(value[0])) {
3321 value++;
3322 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003323
Radek Krejci0d7b2472016-02-12 11:11:03 +01003324 if (!strcmp(value, "unbounded")) {
3325 llist->max = 0;
3326 } else {
3327 /* convert it to uint32_t */
3328 errno = 0;
3329 endptr = NULL;
3330 val = strtoul(value, &endptr, 10);
3331 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003332 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003333 goto error;
3334 }
3335 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003336 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003337 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3338 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003339 goto error;
3340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003342 } else if (!strcmp(sub->name, "when")) {
3343 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003344 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003345 goto error;
3346 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003347
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003348 llist->when = read_yin_when(module, sub);
3349 if (!llist->when) {
3350 goto error;
3351 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003353 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003354 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003356
Michal Vasko88c29542015-11-27 14:57:53 +01003357 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003361 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003362 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 goto error;
3364 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 /* middle part - process nodes with cardinality of 0..n */
3367 if (c_must) {
3368 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003369 if (!llist->must) {
3370 LOGMEM;
3371 goto error;
3372 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003374 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003375 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3376 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003377 LOGMEM;
3378 goto error;
3379 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003380 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003381
Radek Krejci73adb602015-07-02 18:07:40 +02003382 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003384 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3385 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 if (r) {
3387 goto error;
3388 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003389 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003390 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3391 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003392 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003393 goto error;
3394 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003399
3400error:
3401
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003402 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003405}
3406
Michal Vasko0d343d12015-08-24 14:57:36 +02003407/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003408static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003409read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3410 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003411{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003412 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003413 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003415 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003416 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003418 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 char *auxs;
3420 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 /* init */
3423 memset(&root, 0, sizeof root);
3424 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003427 if (!list) {
3428 LOGMEM;
3429 return NULL;
3430 }
Radek Krejci76512572015-08-04 09:47:08 +02003431 list->nodetype = LYS_LIST;
3432 list->prev = (struct lys_node *)list;
3433 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003434
Michal Vaskoe0c59842015-09-24 13:52:20 +02003435 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3436 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 goto error;
3438 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003439
Radek Krejcia9544502015-08-14 08:24:29 +02003440 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3441
Radek Krejciadb30652016-07-11 15:27:07 +02003442 /* insert the node into the schema tree */
3443 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3444 goto error;
3445 }
3446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 /* process list's specific children */
3448 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003449 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3450 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003451 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003452 continue;
3453 }
3454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 /* data statements */
3456 if (!strcmp(sub->name, "container") ||
3457 !strcmp(sub->name, "leaf-list") ||
3458 !strcmp(sub->name, "leaf") ||
3459 !strcmp(sub->name, "list") ||
3460 !strcmp(sub->name, "choice") ||
3461 !strcmp(sub->name, "uses") ||
3462 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003463 !strcmp(sub->name, "anyxml") ||
3464 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003465 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003466 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003468 /* array counters */
3469 } else if (!strcmp(sub->name, "key")) {
3470 /* check cardinality 0..1 */
3471 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003472 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 goto error;
3474 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 /* count the number of keys */
3477 GETVAL(value, sub, "value");
3478 key_str = value;
3479 while ((value = strpbrk(value, " \t\n"))) {
3480 list->keys_size++;
3481 while (isspace(*value)) {
3482 value++;
3483 }
3484 }
3485 list->keys_size++;
3486 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003487 if (!list->keys) {
3488 LOGMEM;
3489 goto error;
3490 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 } else if (!strcmp(sub->name, "unique")) {
3492 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003493 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003494 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 } else if (!strcmp(sub->name, "typedef")) {
3496 c_tpdf++;
3497 } else if (!strcmp(sub->name, "must")) {
3498 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003499 } else if (!strcmp(sub->name, "if-feature")) {
3500 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 /* optional stetments */
3503 } else if (!strcmp(sub->name, "ordered-by")) {
3504 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003505 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 goto error;
3507 }
3508 /* just checking the flags in llist is not sufficient, we would
3509 * allow multiple ordered-by statements with the "system" value
3510 */
3511 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003512
Radek Krejci1574a8d2015-08-03 14:16:52 +02003513 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3515 * state data
3516 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003517 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 continue;
3519 }
Radek Krejci345ad742015-06-03 11:04:18 +02003520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 GETVAL(value, sub, "value");
3522 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003523 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003524 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003525 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 goto error;
3527 }
3528 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003529 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003530 } else if (!strcmp(sub->name, "min-elements")) {
3531 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003532 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 goto error;
3534 }
3535 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 GETVAL(value, sub, "value");
3538 while (isspace(value[0])) {
3539 value++;
3540 }
Radek Krejci345ad742015-06-03 11:04:18 +02003541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 /* convert it to uint32_t */
3543 errno = 0;
3544 auxs = NULL;
3545 val = strtoul(value, &auxs, 10);
3546 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003547 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003548 goto error;
3549 }
3550 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003551 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003552 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3553 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003554 lyxml_free(module->ctx, sub);
3555 goto error;
3556 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003557 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 } else if (!strcmp(sub->name, "max-elements")) {
3559 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003560 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 goto error;
3562 }
3563 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 GETVAL(value, sub, "value");
3566 while (isspace(value[0])) {
3567 value++;
3568 }
Radek Krejci345ad742015-06-03 11:04:18 +02003569
Radek Krejci0d7b2472016-02-12 11:11:03 +01003570 if (!strcmp(value, "unbounded")) {
3571 list->max = 0;;
3572 } else {
3573 /* convert it to uint32_t */
3574 errno = 0;
3575 auxs = NULL;
3576 val = strtoul(value, &auxs, 10);
3577 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003578 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003579 goto error;
3580 }
3581 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003582 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003583 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3584 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003585 goto error;
3586 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003588 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003589 } else if (!strcmp(sub->name, "when")) {
3590 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003591 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003592 goto error;
3593 }
3594
3595 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003596 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003597 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003598 goto error;
3599 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003600 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003601 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003602 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003603 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 }
3605 }
Radek Krejci345ad742015-06-03 11:04:18 +02003606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003608 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003609 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 goto error;
3611 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3614 if (c_tpdf) {
3615 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003616 if (!list->tpdf) {
3617 LOGMEM;
3618 goto error;
3619 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003620 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003621 if (c_must) {
3622 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003623 if (!list->must) {
3624 LOGMEM;
3625 goto error;
3626 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003627 }
3628 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003629 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
3630 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003631 LOGMEM;
3632 goto error;
3633 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003634 }
Radek Krejci73adb602015-07-02 18:07:40 +02003635 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003637 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3638 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 if (r) {
3640 goto error;
3641 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003642 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003643 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
3644 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003645 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003646 goto error;
3647 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003648 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003649 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3650 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003651 if (r) {
3652 goto error;
3653 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 }
3655 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 /* last part - process data nodes */
3658 LY_TREE_FOR_SAFE(root.child, next, sub) {
3659 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003660 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003661 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003662 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003664 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003666 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003668 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003670 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003672 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003673 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003674 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003675 } else if (!strcmp(sub->name, "action")) {
3676 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003677 } else {
3678 LOGINT;
3679 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003681 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 goto error;
3683 }
Radek Krejci73adb602015-07-02 18:07:40 +02003684
Michal Vasko345da0a2015-12-02 10:35:55 +01003685 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003687
Radek Krejci461efb92016-02-12 15:52:18 +01003688 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003689 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003690 goto error;
3691 }
3692 } /* 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 +02003693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 /* process unique statements */
3695 if (c_uniq) {
3696 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003697 if (!list->unique) {
3698 LOGMEM;
3699 goto error;
3700 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003701
Radek Krejci461efb92016-02-12 15:52:18 +01003702 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3703 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3704 list->unique_size++;
3705 if (r) {
3706 goto error;
3707 }
3708
3709 lyxml_free(module->ctx, sub);
3710 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003714
3715error:
3716
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003717 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003719 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
3721 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003722 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003723 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003726}
3727
Michal Vasko0d343d12015-08-24 14:57:36 +02003728/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003729static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003730read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3731 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003732{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003734 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003735 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003736 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003737 const char *value;
3738 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003739 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003741 /* init */
3742 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003745 if (!cont) {
3746 LOGMEM;
3747 return NULL;
3748 }
Radek Krejci76512572015-08-04 09:47:08 +02003749 cont->nodetype = LYS_CONTAINER;
3750 cont->prev = (struct lys_node *)cont;
3751 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003752
Michal Vaskoe0c59842015-09-24 13:52:20 +02003753 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3754 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 goto error;
3756 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757
Radek Krejcia9544502015-08-14 08:24:29 +02003758 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3759
Radek Krejciadb30652016-07-11 15:27:07 +02003760 /* insert the node into the schema tree */
3761 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3762 goto error;
3763 }
3764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 /* process container's specific children */
3766 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003767 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003768 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003769 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003770 continue;
3771 }
3772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 if (!strcmp(sub->name, "presence")) {
3774 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003775 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 goto error;
3777 }
3778 GETVAL(value, sub, "value");
3779 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003780
Michal Vasko345da0a2015-12-02 10:35:55 +01003781 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003782 } else if (!strcmp(sub->name, "when")) {
3783 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003784 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003785 goto error;
3786 }
3787
3788 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003789 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003790 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003791 goto error;
3792 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003793 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 /* data statements */
3796 } else if (!strcmp(sub->name, "container") ||
3797 !strcmp(sub->name, "leaf-list") ||
3798 !strcmp(sub->name, "leaf") ||
3799 !strcmp(sub->name, "list") ||
3800 !strcmp(sub->name, "choice") ||
3801 !strcmp(sub->name, "uses") ||
3802 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003803 !strcmp(sub->name, "anyxml") ||
3804 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003805 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003806 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 /* array counters */
3809 } else if (!strcmp(sub->name, "typedef")) {
3810 c_tpdf++;
3811 } else if (!strcmp(sub->name, "must")) {
3812 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003813 } else if (!strcmp(sub->name, "if-feature")) {
3814 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003816 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 }
3819 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3822 if (c_tpdf) {
3823 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003824 if (!cont->tpdf) {
3825 LOGMEM;
3826 goto error;
3827 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 }
3829 if (c_must) {
3830 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003831 if (!cont->must) {
3832 LOGMEM;
3833 goto error;
3834 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003836 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003837 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
3838 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003839 LOGMEM;
3840 goto error;
3841 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003842 }
Radek Krejci800af702015-06-02 13:46:01 +02003843
Radek Krejci73adb602015-07-02 18:07:40 +02003844 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003846 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3847 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 if (r) {
3849 goto error;
3850 }
3851 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003852 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3853 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 if (r) {
3855 goto error;
3856 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003857 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003858 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
3859 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003860 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003861 goto error;
3862 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003866 /* last part - process data nodes */
3867 LY_TREE_FOR_SAFE(root.child, next, sub) {
3868 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003869 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003871 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003873 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003875 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003877 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003879 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003881 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003883 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003884 } else if (!strcmp(sub->name, "action")) {
3885 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003887 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 goto error;
3889 }
Radek Krejci73adb602015-07-02 18:07:40 +02003890
Michal Vasko345da0a2015-12-02 10:35:55 +01003891 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003893
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003894 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003895
3896error:
3897
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003898 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003900 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003903 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003904}
3905
Michal Vasko0d343d12015-08-24 14:57:36 +02003906/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003907static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003908read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003909 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003910{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003912 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003913 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003914 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 int r;
3916 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 /* init */
3919 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003922 if (!grp) {
3923 LOGMEM;
3924 return NULL;
3925 }
Radek Krejci76512572015-08-04 09:47:08 +02003926 grp->nodetype = LYS_GROUPING;
3927 grp->prev = (struct lys_node *)grp;
3928 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003929
Michal Vasko71e1aa82015-08-12 12:17:51 +02003930 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003931 goto error;
3932 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003933
Radek Krejcia9544502015-08-14 08:24:29 +02003934 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3935
Radek Krejciadb30652016-07-11 15:27:07 +02003936 /* insert the node into the schema tree */
3937 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3938 goto error;
3939 }
3940
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003942 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3943 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003944 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003945 continue;
3946 }
3947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 /* data statements */
3949 if (!strcmp(sub->name, "container") ||
3950 !strcmp(sub->name, "leaf-list") ||
3951 !strcmp(sub->name, "leaf") ||
3952 !strcmp(sub->name, "list") ||
3953 !strcmp(sub->name, "choice") ||
3954 !strcmp(sub->name, "uses") ||
3955 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003956 !strcmp(sub->name, "anyxml") ||
3957 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003958 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003959 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 /* array counters */
3962 } else if (!strcmp(sub->name, "typedef")) {
3963 c_tpdf++;
3964 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003965 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 goto error;
3967 }
3968 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003970 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3971 if (c_tpdf) {
3972 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003973 if (!grp->tpdf) {
3974 LOGMEM;
3975 goto error;
3976 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003978 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003979 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3980 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003981 if (r) {
3982 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003983 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003984 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02003987 if (!root.child) {
3988 LOGWRN("Grouping \"%s\" without children.", retval->name);
3989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003990 LY_TREE_FOR_SAFE(root.child, next, sub) {
3991 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003992 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003993 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003994 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003995 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003996 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003997 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003998 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003999 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004000 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004002 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004004 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004006 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004007 } else if (!strcmp(sub->name, "action")) {
4008 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004010 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004011 goto error;
4012 }
Radek Krejci73adb602015-07-02 18:07:40 +02004013
Michal Vasko345da0a2015-12-02 10:35:55 +01004014 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004018
4019error:
4020
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004021 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004022 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004023 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004024 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004027}
4028
Michal Vasko0d343d12015-08-24 14:57:36 +02004029/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004030static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004031read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4032 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004033{
Radek Krejcie0674f82015-06-15 13:58:51 +02004034 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004035 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004036 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004037 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004038 int r;
4039 int c_tpdf = 0;
4040
Radek Krejcie0674f82015-06-15 13:58:51 +02004041 /* init */
4042 memset(&root, 0, sizeof root);
4043
Michal Vasko38d01f72015-06-15 09:41:06 +02004044 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004045 if (!inout) {
4046 LOGMEM;
4047 return NULL;
4048 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004049 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004050
4051 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004052 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004053 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004054 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004055 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004056 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004057 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004058 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004059 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004060 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004061 }
4062
Radek Krejci76512572015-08-04 09:47:08 +02004063 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004064
Radek Krejci6a113852015-07-03 16:04:20 +02004065 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004066 goto error;
4067 }
4068
Radek Krejcia9544502015-08-14 08:24:29 +02004069 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4070
Radek Krejciadb30652016-07-11 15:27:07 +02004071 /* insert the node into the schema tree */
4072 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4073 goto error;
4074 }
4075
Michal Vasko38d01f72015-06-15 09:41:06 +02004076 /* data statements */
4077 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004078 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4079 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004080 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004081 continue;
4082 }
4083
Michal Vasko38d01f72015-06-15 09:41:06 +02004084 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004085 !strcmp(sub->name, "leaf-list") ||
4086 !strcmp(sub->name, "leaf") ||
4087 !strcmp(sub->name, "list") ||
4088 !strcmp(sub->name, "choice") ||
4089 !strcmp(sub->name, "uses") ||
4090 !strcmp(sub->name, "grouping") ||
4091 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004092 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004093 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004095 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004096 } else if (!strcmp(sub->name, "typedef")) {
4097 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004098
Michal Vasko38d01f72015-06-15 09:41:06 +02004099 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004100 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004102 }
4103 }
4104
4105 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4106 if (c_tpdf) {
4107 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004108 if (!inout->tpdf) {
4109 LOGMEM;
4110 goto error;
4111 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004112 }
4113
Radek Krejci73adb602015-07-02 18:07:40 +02004114 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004115 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4116 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004117 if (r) {
4118 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004119 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004120 }
4121
4122 /* last part - process data nodes */
4123 LY_TREE_FOR_SAFE(root.child, next, sub) {
4124 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004125 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004126 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004127 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004128 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004129 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004130 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004131 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004132 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004133 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004134 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004135 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004136 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004137 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004138 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004139 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004140 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004141 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004142 goto error;
4143 }
Radek Krejci73adb602015-07-02 18:07:40 +02004144
Michal Vasko345da0a2015-12-02 10:35:55 +01004145 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004146 }
4147
Michal Vasko38d01f72015-06-15 09:41:06 +02004148 return retval;
4149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004150error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004151
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004152 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004153 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004154 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 }
4156
4157 return NULL;
4158}
4159
Michal Vasko0d343d12015-08-24 14:57:36 +02004160/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004161static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004162read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4163 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004164{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004165 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004166 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004167 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004168 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004169 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004170 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004171
Michal Vaskoc6551b32015-06-16 10:51:43 +02004172 memset(&root, 0, sizeof root);
4173
Michal Vasko0ea41032015-06-16 08:53:55 +02004174 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004175 if (!notif) {
4176 LOGMEM;
4177 return NULL;
4178 }
Radek Krejci76512572015-08-04 09:47:08 +02004179 notif->nodetype = LYS_NOTIF;
4180 notif->prev = (struct lys_node *)notif;
4181 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004182
Radek Krejci6a113852015-07-03 16:04:20 +02004183 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004184 goto error;
4185 }
4186
Radek Krejcia9544502015-08-14 08:24:29 +02004187 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4188
Radek Krejciadb30652016-07-11 15:27:07 +02004189 /* insert the node into the schema tree */
4190 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4191 goto error;
4192 }
4193
Michal Vasko0ea41032015-06-16 08:53:55 +02004194 /* process rpc's specific children */
4195 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004196 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4197 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004198 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004199 continue;
4200 }
4201
Michal Vasko0ea41032015-06-16 08:53:55 +02004202 /* data statements */
4203 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004204 !strcmp(sub->name, "leaf-list") ||
4205 !strcmp(sub->name, "leaf") ||
4206 !strcmp(sub->name, "list") ||
4207 !strcmp(sub->name, "choice") ||
4208 !strcmp(sub->name, "uses") ||
4209 !strcmp(sub->name, "grouping") ||
4210 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004211 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004212 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004215 } else if (!strcmp(sub->name, "typedef")) {
4216 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004217 } else if (!strcmp(sub->name, "if-feature")) {
4218 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004219 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004220 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004221 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004222 }
4223 }
4224
4225 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4226 if (c_tpdf) {
4227 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004228 if (!notif->tpdf) {
4229 LOGMEM;
4230 goto error;
4231 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004232 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004233 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004234 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4235 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004236 LOGMEM;
4237 goto error;
4238 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004239 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004240
Radek Krejci73adb602015-07-02 18:07:40 +02004241 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004243 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4244 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004245 if (r) {
4246 goto error;
4247 }
Radek Krejci96299152016-06-22 10:17:50 +02004248 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004249 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4250 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004251 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004252 goto error;
4253 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004254 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004255 }
4256
4257 /* last part - process data nodes */
4258 LY_TREE_FOR_SAFE(root.child, next, sub) {
4259 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004260 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004261 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004262 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004263 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004264 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004266 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004267 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004268 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004269 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004270 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004271 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004272 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004273 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004274 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004275 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004276 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004277 goto error;
4278 }
Radek Krejci73adb602015-07-02 18:07:40 +02004279
Michal Vasko345da0a2015-12-02 10:35:55 +01004280 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004281 }
4282
Michal Vasko0ea41032015-06-16 08:53:55 +02004283 return retval;
4284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004286
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004287 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004288 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004289 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004290 }
4291
4292 return NULL;
4293}
4294
Michal Vasko0d343d12015-08-24 14:57:36 +02004295/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004296static struct lys_node *
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004297read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4298 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004299{
Radek Krejcie0674f82015-06-15 13:58:51 +02004300 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004301 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004302 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004303 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004304 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004305 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004306
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004307 if (!strcmp(yin->name, "action")) {
4308 for (node = parent; node; node = lys_parent(node)) {
4309 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
4310 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
4311 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
4312 return NULL;
4313 }
4314 }
4315 }
4316
Radek Krejcie0674f82015-06-15 13:58:51 +02004317 /* init */
4318 memset(&root, 0, sizeof root);
4319
Michal Vasko38d01f72015-06-15 09:41:06 +02004320 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004321 if (!rpc) {
4322 LOGMEM;
4323 return NULL;
4324 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004325 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02004326 rpc->prev = (struct lys_node *)rpc;
4327 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004328
Radek Krejci6a113852015-07-03 16:04:20 +02004329 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004330 goto error;
4331 }
4332
Radek Krejcia9544502015-08-14 08:24:29 +02004333 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4334
Radek Krejciadb30652016-07-11 15:27:07 +02004335 /* insert the node into the schema tree */
4336 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4337 goto error;
4338 }
4339
Michal Vasko38d01f72015-06-15 09:41:06 +02004340 /* process rpc's specific children */
4341 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004342 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4343 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004344 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004345 continue;
4346 }
4347
Michal Vasko38d01f72015-06-15 09:41:06 +02004348 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004349 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004350 && (rpc->child->nodetype == LYS_INPUT
4351 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004352 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004353 goto error;
4354 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004355 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004356 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004357 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004358 if (rpc->child
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004359 && (rpc->child->nodetype == LYS_OUTPUT
4360 || (rpc->child->next && rpc->child->next->nodetype == LYS_OUTPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004361 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004362 goto error;
4363 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004364 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004365 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004368 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004369 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004370 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004372 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004373 } else if (!strcmp(sub->name, "typedef")) {
4374 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004375 } else if (!strcmp(sub->name, "if-feature")) {
4376 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004377 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004378 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004379 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004380 }
4381 }
4382
4383 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4384 if (c_tpdf) {
4385 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004386 if (!rpc->tpdf) {
4387 LOGMEM;
4388 goto error;
4389 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004390 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004391 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004392 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
4393 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004394 LOGMEM;
4395 goto error;
4396 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004397 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004398
Radek Krejci73adb602015-07-02 18:07:40 +02004399 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004400 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004401 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4402 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004403 if (r) {
4404 goto error;
4405 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004406 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004407 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
4408 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004409 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004410 goto error;
4411 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004412 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004413 }
4414
4415 /* last part - process data nodes */
4416 LY_TREE_FOR_SAFE(root.child, next, sub) {
4417 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004418 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004419 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004420 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004421 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004422 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004423 goto error;
4424 }
Radek Krejci73adb602015-07-02 18:07:40 +02004425
Michal Vasko345da0a2015-12-02 10:35:55 +01004426 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004427 }
4428
Michal Vasko38d01f72015-06-15 09:41:06 +02004429 return retval;
4430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004431error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004432
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004433 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004434 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004435 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004436 }
4437
4438 return NULL;
4439}
4440
Michal Vasko0d343d12015-08-24 14:57:36 +02004441/* logs directly
4442 *
Radek Krejci74705112015-06-05 10:25:44 +02004443 * resolve - referenced grouping should be bounded to the namespace (resolved)
4444 * only when uses does not appear in grouping. In a case of grouping's uses,
4445 * we just get information but we do not apply augment or refine to it.
4446 */
Radek Krejci76512572015-08-04 09:47:08 +02004447static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02004448read_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 +02004449{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004450 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004451 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004452 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004454 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004455 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004457 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004458 if (!uses) {
4459 LOGMEM;
4460 return NULL;
4461 }
Radek Krejci76512572015-08-04 09:47:08 +02004462 uses->nodetype = LYS_USES;
4463 uses->prev = (struct lys_node *)uses;
4464 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004465
Radek Krejcia9544502015-08-14 08:24:29 +02004466 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004468
Michal Vaskoe0c59842015-09-24 13:52:20 +02004469 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02004470 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 goto error;
4472 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004473
Radek Krejcia9544502015-08-14 08:24:29 +02004474 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4475
Radek Krejciadb30652016-07-11 15:27:07 +02004476 /* insert the node into the schema tree */
4477 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4478 goto error;
4479 }
4480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004482 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004483 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4484 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004485 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004486 continue;
4487 }
4488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 if (!strcmp(sub->name, "refine")) {
4490 c_ref++;
4491 } else if (!strcmp(sub->name, "augment")) {
4492 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004493 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004494 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004495 } else if (!strcmp(sub->name, "when")) {
4496 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004497 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004498 goto error;
4499 }
4500
4501 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004502 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004503 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004504 goto error;
4505 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004506 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004508 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 }
4511 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 /* process properties with cardinality 0..n */
4514 if (c_ref) {
4515 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004516 if (!uses->refine) {
4517 LOGMEM;
4518 goto error;
4519 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 }
4521 if (c_aug) {
4522 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004523 if (!uses->augment) {
4524 LOGMEM;
4525 goto error;
4526 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004528 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004529 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
4530 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004531 LOGMEM;
4532 goto error;
4533 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004534 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004535
Radek Krejcia9544502015-08-14 08:24:29 +02004536 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004538 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4539 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004540 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004541 goto error;
4542 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004543 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004544 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4545 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004546 if (r) {
4547 goto error;
4548 }
4549 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004550 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
4551 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004552 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004553 goto error;
4554 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 }
4556 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004557
Radek Krejci48464ed2016-03-17 15:44:09 +01004558 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004559 goto error;
4560 }
Radek Krejci74705112015-06-05 10:25:44 +02004561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004562 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004563
4564error:
4565
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004566 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004569}
4570
Michal Vasko0d343d12015-08-24 14:57:36 +02004571/* logs directly
4572 *
4573 * common code for yin_read_module() and yin_read_submodule()
4574 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004575static int
Radek Krejcic071c542016-01-27 14:57:51 +01004576read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4577 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004578{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004580 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004581 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004582 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004583 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004585 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02004586 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01004587 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004588 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004589 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 +02004590
Radek Krejcic071c542016-01-27 14:57:51 +01004591 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004592 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 /* init */
4595 memset(&root, 0, sizeof root);
4596 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004597 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 /*
4600 * in the first run, we process elements with cardinality of 1 or 0..1 and
4601 * count elements with cardinality 0..n. Data elements (choices, containers,
4602 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4603 * need have all top-level and groupings already prepared at that time. In
4604 * the middle loop, we process other elements with carinality of 0..n since
4605 * we need to allocate arrays to store them.
4606 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 LY_TREE_FOR_SAFE(yin->child, next, child) {
4608 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004609 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004610 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004611 continue;
4612 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004613
Radek Krejcic071c542016-01-27 14:57:51 +01004614 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004616 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 goto error;
4618 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004620 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004621 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004622 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004624 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 goto error;
4626 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004628 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 goto error;
4630 }
4631 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004632 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004633 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4634 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004635 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 goto error;
4637 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004638 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004639 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004640 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 goto error;
4642 }
Radek Krejcif3886932015-06-04 17:36:06 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004645 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004646 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004648 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004649 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004652 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 goto error;
4654 }
4655 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004656 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 /* check here differs from a generic prefix check, since this prefix
4658 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004659 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004660 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 goto error;
4662 }
Radek Krejcic071c542016-01-27 14:57:51 +01004663 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004666 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004667
4668 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004669 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004670 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004673 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004675 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004677 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004679 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004680 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004681 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004682 lyxml_unlink_elem(ctx, child, 2);
4683 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004684
Radek Krejci1d82ef62015-08-07 14:44:40 +02004685 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004686 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004687 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004688 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004691 } else if (!strcmp(child->name, "container") ||
4692 !strcmp(child->name, "leaf-list") ||
4693 !strcmp(child->name, "leaf") ||
4694 !strcmp(child->name, "list") ||
4695 !strcmp(child->name, "choice") ||
4696 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004697 !strcmp(child->name, "anyxml") ||
4698 !strcmp(child->name, "rpc") ||
4699 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004700 lyxml_unlink_elem(ctx, child, 2);
4701 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004702
Radek Krejci1d82ef62015-08-07 14:44:40 +02004703 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004705 lyxml_unlink_elem(ctx, child, 2);
4706 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004709 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004710 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004711 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004712 goto error;
4713 }
Radek Krejcic071c542016-01-27 14:57:51 +01004714 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004715 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004716 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004717 goto error;
4718 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004719 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004720 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004721 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 goto error;
4723 }
Radek Krejcic071c542016-01-27 14:57:51 +01004724 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004725 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004726 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004729 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004730 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004731 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 goto error;
4733 }
Radek Krejcic071c542016-01-27 14:57:51 +01004734 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004735 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004736 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 goto error;
4738 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004739 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004740 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004741 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 goto error;
4743 }
Radek Krejcic071c542016-01-27 14:57:51 +01004744 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004745 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004746 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 goto error;
4748 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004749 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004750 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004751 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 goto error;
4753 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004754 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02004755 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004756 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 goto error;
4758 }
Radek Krejcic071c542016-01-27 14:57:51 +01004759 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02004760 if (!strcmp(value, "1")) {
4761 if (submodule) {
4762 if (module->version > 1) {
4763 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4764 goto error;
4765 }
4766 } else {
4767 module->version = 1;
4768 }
4769 } else {
4770 if (submodule) {
4771 if (module->version != 2) {
4772 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4773 goto error;
4774 }
4775 } else {
4776 module->version = 2;
4777 }
4778 }
4779
Michal Vasko345da0a2015-12-02 10:35:55 +01004780 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004781
Radek Krejci1d82ef62015-08-07 14:44:40 +02004782 } else if (!strcmp(child->name, "extension")) {
4783 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004784
Radek Krejci3d468122015-10-02 13:36:12 +02004785 /* we have the following supported (hardcoded) extensions: */
4786 /* ietf-netconf's get-filter-element-attributes */
4787 if (!strcmp(module->ns, LY_NSNC) &&
4788 !strcmp(value, "get-filter-element-attributes")) {
4789 LOGDBG("NETCONF filter extension found");
4790 /* NACM's default-deny-write and default-deny-all */
4791 } else if (!strcmp(module->ns, LY_NSNACM) &&
4792 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4793 LOGDBG("NACM extension found");
4794 /* other extensions are not supported, so inform about such an extension */
4795 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004796 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004797 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004798 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004800 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 }
4803 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004804
Radek Krejcic071c542016-01-27 14:57:51 +01004805 /* check for mandatory statements */
4806 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004807 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004808 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004809 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004811 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 goto error;
4813 }
4814 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004815 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 goto error;
4817 }
4818 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004820 /* allocate arrays for elements with cardinality of 0..n */
4821 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004822 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
4823 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004824 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004825 LOGMEM;
4826 goto error;
4827 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004828 /* set stop block for possible realloc */
4829 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 }
4831 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004832 trg->rev = calloc(c_rev, sizeof *trg->rev);
4833 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004834 LOGMEM;
4835 goto error;
4836 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837 }
4838 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004839 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4840 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004841 LOGMEM;
4842 goto error;
4843 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 }
4845 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004846 trg->ident = calloc(c_ident, sizeof *trg->ident);
4847 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004848 LOGMEM;
4849 goto error;
4850 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 }
4852 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004853 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
4854 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004855 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004856 LOGMEM;
4857 goto error;
4858 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004859 /* set stop block for possible realloc */
4860 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004862 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004863 trg->augment = calloc(c_aug, sizeof *trg->augment);
4864 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004865 LOGMEM;
4866 goto error;
4867 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004868 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004869 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004870 trg->features = calloc(c_ftrs, sizeof *trg->features);
4871 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004872 LOGMEM;
4873 goto error;
4874 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004875 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004876 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004877 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4878 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004879 LOGMEM;
4880 goto error;
4881 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004882 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004883
Michal Vasko2f7925f2015-10-21 15:06:56 +02004884 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4885 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004886 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004887 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4888 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 if (r) {
4890 goto error;
4891 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004892
Radek Krejci1d82ef62015-08-07 14:44:40 +02004893 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004894 memset(&inc, 0, sizeof inc);
4895 /* 1) pass module, not trg, since we want to pass the main module
4896 * 2) we cannot pass directly the structure in the array since
4897 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004898 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004899 if (!r) {
4900 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02004901 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
4902 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004903 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004904 goto error;
4905 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004906
Radek Krejci1d82ef62015-08-07 14:44:40 +02004907 } else if (!strcmp(child->name, "revision")) {
4908 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004909 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004910 goto error;
4911 }
Radek Krejcic071c542016-01-27 14:57:51 +01004912 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004913 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004914 for (i = 0; i < trg->rev_size; i++) {
4915 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004916 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4917 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004918 }
4919 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004920
Radek Krejci1d82ef62015-08-07 14:44:40 +02004921 LY_TREE_FOR(child->child, child2) {
4922 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004923 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004924 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004925 goto error;
4926 }
Radek Krejcic071c542016-01-27 14:57:51 +01004927 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4928 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 goto error;
4930 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004931 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004932 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004933 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004934 goto error;
4935 }
Radek Krejcic071c542016-01-27 14:57:51 +01004936 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4937 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004938 goto error;
4939 }
4940 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004941 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 goto error;
4943 }
4944 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004947 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004948 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004949 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004950 if (!value) {
4951 LOGMEM;
4952 goto error;
4953 }
Radek Krejcic071c542016-01-27 14:57:51 +01004954 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4955 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004957
Radek Krejci749190d2016-02-18 16:26:25 +01004958 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004959 value = trg->rev[0].dsc;
4960 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4961 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004962 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004963
Radek Krejci749190d2016-02-18 16:26:25 +01004964 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004965 value = trg->rev[0].ref;
4966 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4967 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004968 }
4969 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004970
Radek Krejcic071c542016-01-27 14:57:51 +01004971 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004972
Radek Krejci1d82ef62015-08-07 14:44:40 +02004973 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004974 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4975 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 if (r) {
4977 goto error;
4978 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004979
Radek Krejci1d82ef62015-08-07 14:44:40 +02004980 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004981 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4982 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 if (r) {
4984 goto error;
4985 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004986
Radek Krejci1d82ef62015-08-07 14:44:40 +02004987 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004988 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4989 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004990 if (r) {
4991 goto error;
4992 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004993
Radek Krejci1d82ef62015-08-07 14:44:40 +02004994 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004995 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4996 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004997 if (r) {
4998 goto error;
4999 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005000 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5001 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005005
Radek Krejcib8f98c12016-06-24 10:30:46 +02005006 if (!submodule) {
5007 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005008 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005009 if (module->inc_size) {
5010 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5011 if (!module->inc) {
5012 LOGMEM;
5013 goto error;
5014 }
5015 }
5016 if (module->imp_size) {
5017 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5018 if (!module->imp) {
5019 LOGMEM;
5020 goto error;
5021 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005022 }
5023 }
Radek Krejcic071c542016-01-27 14:57:51 +01005024
Radek Krejcif5be10f2015-06-16 13:29:36 +02005025 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005026 * refer to them. Submodule's data nodes are stored in the
5027 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005029 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005030 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005031 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 goto error;
5033 }
Radek Krejci74705112015-06-05 10:25:44 +02005034
Michal Vasko345da0a2015-12-02 10:35:55 +01005035 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005036 }
Radek Krejci74705112015-06-05 10:25:44 +02005037
Radek Krejcif5be10f2015-06-16 13:29:36 +02005038 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005039 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005040
Radek Krejci1d82ef62015-08-07 14:44:40 +02005041 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005042 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005043 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005044 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005045 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005046 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005047 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005048 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005049 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005050 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005051 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005052 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005053 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005054 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005055 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005056 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005057 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005058 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005059 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005060 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005061 goto error;
5062 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005063
Michal Vasko345da0a2015-12-02 10:35:55 +01005064 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005066
Michal Vasko2f7925f2015-10-21 15:06:56 +02005067 /* ... and finally augments (last, so we can augment our data, for instance) */
5068 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005069 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5070 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005071
Michal Vasko2f7925f2015-10-21 15:06:56 +02005072 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005073 goto error;
5074 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005075 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005076 }
5077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005078 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005079
5080error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005081 /* cleanup */
5082 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005083 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005084 }
5085 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005086 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005087 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005088 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005089 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005090 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005092 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005093}
5094
Michal Vasko0d343d12015-08-24 14:57:36 +02005095/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005096struct lys_submodule *
5097yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005098{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005099 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005100 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005101 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005102
Michal Vasko5a721fd2016-02-16 12:16:48 +01005103 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005104
Radek Krejci722b0072016-02-01 17:09:45 +01005105 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005107 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005108 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005110 /* check root element */
5111 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005112 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005113 goto error;
5114 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005117 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005118 goto error;
5119 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005120
Michal Vasko5a721fd2016-02-16 12:16:48 +01005121 submodule = calloc(1, sizeof *submodule);
5122 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005123 LOGMEM;
5124 goto error;
5125 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005126
Michal Vasko5a721fd2016-02-16 12:16:48 +01005127 submodule->ctx = module->ctx;
5128 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5129 submodule->type = 1;
5130 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005131
Michal Vasko5a721fd2016-02-16 12:16:48 +01005132 LOGVRB("Reading submodule \"%s\".", submodule->name);
5133 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 goto error;
5135 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005138 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005139
Michal Vasko5a721fd2016-02-16 12:16:48 +01005140 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005141 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005142
5143error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005144 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005145 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005146 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005147
Michal Vasko5a721fd2016-02-16 12:16:48 +01005148 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005149 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005150 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005151 }
5152
Michal Vasko5a721fd2016-02-16 12:16:48 +01005153 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005154
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005155 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5156 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005157 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005158 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005159}
5160
Michal Vasko0d343d12015-08-24 14:57:36 +02005161/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005162struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005163yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005164{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005165 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005166 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005167 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005168 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005169 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005170
Radek Krejcic071c542016-01-27 14:57:51 +01005171 unres = calloc(1, sizeof *unres);
5172 if (!unres) {
5173 LOGMEM;
5174 return NULL;
5175 }
5176
Radek Krejci722b0072016-02-01 17:09:45 +01005177 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005178 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005179 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005180 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005182 /* check root element */
5183 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005184 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 goto error;
5186 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005189 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 goto error;
5191 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 module = calloc(1, sizeof *module);
5194 if (!module) {
5195 LOGMEM;
5196 goto error;
5197 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005199 module->ctx = ctx;
5200 module->name = lydict_insert(ctx, value, strlen(value));
5201 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005202 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005203
Michal Vasko9f258e42016-02-11 11:36:27 +01005204 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005205 if (read_sub_module(module, NULL, yin, unres)) {
5206 goto error;
5207 }
5208
5209 /* resolve rest of unres items */
5210 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 goto error;
5212 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005213
Radek Krejciff4874d2016-03-07 12:30:50 +01005214 if (revision) {
5215 /* check revision of the parsed model */
5216 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005217 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5218 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005219 goto error;
5220 }
5221 }
5222
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005223 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005224 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005226
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005227 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005228 if (!module->implemented) {
5229 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5230 }
Michal Vasko26055752016-05-03 11:36:31 +02005231 if (lys_module_set_implement(module)) {
5232 goto error;
5233 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005234
Michal Vasko26055752016-05-03 11:36:31 +02005235 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5236 goto error;
5237 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005238 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005239 if (!module->inc[i].submodule) {
5240 continue;
5241 }
Michal Vasko26055752016-05-03 11:36:31 +02005242 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5243 goto error;
5244 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005245 }
5246 }
5247
Michal Vasko345da0a2015-12-02 10:35:55 +01005248 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005249 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005250 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005251 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005252
5253error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005255 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005256 unres_schema_free(module, &unres);
5257
5258 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005259 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005260 return NULL;
5261 }
5262
5263 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005264
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005265 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005266 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005267 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005268}