blob: 76a2ed44f990c2bcdd5bd25fa15f0b420643047c [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);
70static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020071
Michal Vasko0d343d12015-08-24 14:57:36 +020072/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020073static const char *
74read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020075{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020076 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020078 /* there should be <text> child */
79 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010080 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010081 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010082 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020083 } else if (node->child->content) {
84 len = strlen(node->child->content);
85 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010086 } else {
87 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020088 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020089}
90
Michal Vasko0d343d12015-08-24 14:57:36 +020091/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020092static int
Michal Vasko1d337e12016-02-15 12:32:04 +010093fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
94{
95 int r;
96 const char *value;
97
98 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +010099 if (!(value = transform_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100100 return EXIT_FAILURE;
101 }
102
103 /* HACK - store pointer to the parent node for later status check */
104 *iffeat = (struct lys_feature *)parent;
Radek Krejci48464ed2016-03-17 15:44:09 +0100105 r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value);
Michal Vasko1d337e12016-02-15 12:32:04 +0100106 lydict_remove(parent->module->ctx, value);
107 if (!r) {
108 return EXIT_SUCCESS;
109 }
110
111error:
112 return EXIT_FAILURE;
113}
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
Radek Krejci73adb602015-07-02 18:07:40 +0200130 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200131 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
132 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200133 continue;
134 }
135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200136 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100137 if (base_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100138 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200139 return EXIT_FAILURE;
140 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100141 base_flag = 1;
142
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200143 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100144 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100145 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200146 return EXIT_FAILURE;
147 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100148
Radek Krejci48464ed2016-03-17 15:44:09 +0100149 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100150 lydict_remove(module->ctx, value);
151 return EXIT_FAILURE;
152 }
153 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200154 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100155 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200156 return EXIT_FAILURE;
157 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200158 }
Radek Krejci04581c62015-05-22 21:24:00 +0200159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200160 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200161
162error:
163 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200164}
165
Michal Vasko0d343d12015-08-24 14:57:36 +0200166/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200167static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200168read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200169{
Radek Krejci73adb602015-07-02 18:07:40 +0200170 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200171 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200172
Radek Krejci73adb602015-07-02 18:07:40 +0200173 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200174 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
175 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200176 continue;
177 }
178
Radek Krejci41726f92015-06-19 13:11:05 +0200179 if (!strcmp(child->name, "description")) {
180 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100181 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200182 return EXIT_FAILURE;
183 }
184 restr->dsc = read_yin_subnode(ctx, child, "text");
185 if (!restr->dsc) {
186 return EXIT_FAILURE;
187 }
188 } else if (!strcmp(child->name, "reference")) {
189 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100190 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200191 return EXIT_FAILURE;
192 }
193 restr->ref = read_yin_subnode(ctx, child, "text");
194 if (!restr->ref) {
195 return EXIT_FAILURE;
196 }
197 } else if (!strcmp(child->name, "error-app-tag")) {
198 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100199 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200200 return EXIT_FAILURE;
201 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200202 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200203 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200204 } else if (!strcmp(child->name, "error-message")) {
205 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100206 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200207 return EXIT_FAILURE;
208 }
209 restr->emsg = read_yin_subnode(ctx, child, "value");
210 if (!restr->emsg) {
211 return EXIT_FAILURE;
212 }
213 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100214 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200215 return EXIT_FAILURE;
216 }
Radek Krejci41726f92015-06-19 13:11:05 +0200217 }
218
219 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200220
221error:
222 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200223}
224
Michal Vasko88c29542015-11-27 14:57:53 +0100225/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
226int
Radek Krejcib8048692015-08-05 13:36:34 +0200227fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Michal Vaskof02e3742015-08-05 16:27:02 +0200228 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200229{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200230 const char *value, *name;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200231 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200232 struct lys_restr **restr;
233 struct lys_type_bit bit;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200234 struct lys_type *type_der;
Radek Krejcifc8d8322016-06-24 11:23:23 +0200235 int i, j, rc, val_set;
Radek Krejcidc008d72016-02-17 13:12:14 +0100236 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200237 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200238 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200239
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200240 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100241 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200242 if (!value) {
243 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200244 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200245
246 i = parse_identifier(value);
247 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100248 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100249 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200250 goto error;
251 }
252 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100253 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200254 if (value[i]) {
255 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100256 name += i;
257 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100258 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100259 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200260 goto error;
261 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200262 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100263 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200264 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200265
Radek Krejci225376f2016-02-16 17:36:22 +0100266 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200267 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100268 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200269 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200270 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100271
272 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200273 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200274 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200275 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100276 ret = EXIT_FAILURE;
277 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200278 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200279 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200280 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200281
Radek Krejcicf509982015-12-15 09:22:44 +0100282 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100283 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100284 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100285 return -1;
286 }
287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200288 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200289 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200290 /* RFC 6020 9.7.4 - bit */
291
292 /* get bit specifications, at least one must be present */
293 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200294 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
295 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100296 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200297 continue;
298 }
299
Radek Krejci994b6f62015-06-18 16:47:27 +0200300 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200301 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200302 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100303 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200304 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200305 }
306 }
Radek Krejciac781922015-07-09 15:35:14 +0200307 if (!type->der->type.der && !type->info.bits.count) {
308 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100309 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200310 goto error;
311 }
Radek Krejciac781922015-07-09 15:35:14 +0200312 if (type->der->type.der && type->info.bits.count) {
313 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100314 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200315 goto error;
316 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200317
318 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100319 if (!type->info.bits.bit) {
320 LOGMEM;
321 goto error;
322 }
Radek Krejci73adb602015-07-02 18:07:40 +0200323 p = 0;
324 i = -1;
325 LY_TREE_FOR(yin->child, next) {
326 i++;
327
328 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100329 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100330 goto error;
331 }
332
Radek Krejci994b6f62015-06-18 16:47:27 +0200333 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200334 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200335 type->info.bits.count = i + 1;
336 goto error;
337 }
338
339 /* check the name uniqueness */
340 for (j = 0; j < i; j++) {
341 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100342 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200343 type->info.bits.count = i + 1;
344 goto error;
345 }
346 }
347
Radek Krejci0d70c372015-07-02 16:23:10 +0200348 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200349 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200350 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
351 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200352 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200353 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200354
Radek Krejci0d70c372015-07-02 16:23:10 +0200355 if (!strcmp(node->name, "position")) {
356 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200357 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200358
359 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200360 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100361 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200362 type->info.bits.count = i + 1;
363 goto error;
364 }
365 type->info.bits.bit[i].pos = (uint32_t)p_;
366
367 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200368 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200369 p = type->info.bits.bit[i].pos;
370 p++;
371 } else {
372 /* check that the value is unique */
373 for (j = 0; j < i; j++) {
374 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100375 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100376 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200377 type->info.bits.count = i + 1;
378 goto error;
379 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200380 }
381 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200382 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100383 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200384 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200385 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200386 }
387 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200388 /* assign value automatically */
389 if (p > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100390 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200391 type->info.bits.count = i + 1;
392 goto error;
393 }
394 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100395 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200396 p++;
397 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200398
399 /* keep them ordered by position */
400 j = i;
401 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
402 /* switch them */
403 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
404 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
405 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
406 j--;
407 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200408 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200409 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200411 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200412 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200413 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200414 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
415 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200416 continue;
417 }
418
Radek Krejcif9401c32015-06-26 16:47:36 +0200419 if (!strcmp(node->name, "range")) {
420 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100421 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200422 goto error;
423 }
424
425 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200426 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100427 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200428 goto error;
429 }
430 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100431 if (!type->info.dec64.range) {
432 LOGMEM;
433 goto error;
434 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200435 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
436
437 /* get possible substatements */
438 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
439 goto error;
440 }
441 } else if (!strcmp(node->name, "fraction-digits")) {
442 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100443 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200444 goto error;
445 }
446 GETVAL(value, node, "value");
447 v = strtol(value, NULL, 10);
448
449 /* range check */
450 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100451 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200452 goto error;
453 }
454 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200455 type->info.dec64.div = 10;
456 for (i = 1; i < v; i++) {
457 type->info.dec64.div *= 10;
458 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200459 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100460 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200461 goto error;
462 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200463 }
464
465 /* mandatory sub-statement(s) check */
466 if (!type->info.dec64.dig && !type->der->type.der) {
467 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100468 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200469 goto error;
470 }
Radek Krejci7511f402015-07-10 09:56:30 +0200471 if (type->info.dec64.dig && type->der->type.der) {
472 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100473 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200474 goto error;
475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200476 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200478 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200479 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200480
Radek Krejci994b6f62015-06-18 16:47:27 +0200481 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200483 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
484 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100485 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200486 continue;
487 }
488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200490 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200491 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100492 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200493 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494 }
495 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200496 if (!type->der->type.der && !type->info.enums.count) {
497 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100498 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 goto error;
500 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200501 if (type->der->type.der && type->info.enums.count) {
502 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100503 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200504 goto error;
505 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200506
Radek Krejci1574a8d2015-08-03 14:16:52 +0200507 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100508 if (!type->info.enums.enm) {
509 LOGMEM;
510 goto error;
511 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200512
513 val_set = v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200514 i = -1;
515 LY_TREE_FOR(yin->child, next) {
516 i++;
517
518 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100519 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100520 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
521 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100522 goto error;
523 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200524 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200525 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200526 type->info.enums.count = i + 1;
527 goto error;
528 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200531 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200532 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100533 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200534 type->info.enums.count = i + 1;
535 goto error;
536 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200538 /* check the name uniqueness */
539 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200540 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100541 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200542 type->info.enums.count = i + 1;
543 goto error;
544 }
545 }
Radek Krejci04581c62015-05-22 21:24:00 +0200546
Radek Krejci73adb602015-07-02 18:07:40 +0200547 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200548 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
549 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200550 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200551 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200552
Radek Krejci0d70c372015-07-02 16:23:10 +0200553 if (!strcmp(node->name, "value")) {
554 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200555 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200556
557 /* range check */
558 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100559 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200560 type->info.enums.count = i + 1;
561 goto error;
562 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200563 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200564
565 /* keep the highest enum value for automatic increment */
Radek Krejcifc8d8322016-06-24 11:23:23 +0200566 if (!val_set || type->info.enums.enm[i].value > v) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200567 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200568 v++;
569 } else {
570 /* check that the value is unique */
571 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200572 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100573 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100574 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200575 type->info.enums.count = i + 1;
576 goto error;
577 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 }
579 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200580 val_set = 1;
Radek Krejci0d70c372015-07-02 16:23:10 +0200581 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100582 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200583 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200585 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200586 if (!val_set) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 /* assign value automatically */
588 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100589 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 type->info.enums.count = i + 1;
591 goto error;
592 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200593 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100594 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 v++;
596 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 }
598 break;
599
600 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200601 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602
603 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200604 LY_TREE_FOR_SAFE(yin->child, next, node) {
605 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
606 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100607 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200608 continue;
609 }
610
Michal Vaskoe29c6622015-11-27 15:02:31 +0100611 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100612 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200613 goto error;
614 }
615 }
616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200617 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200618 if (type->der->type.der) {
619 /* this is just a derived type with no base specified/required */
620 break;
621 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100622 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 goto error;
624 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200625 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100626 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200627 goto error;
628 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200629 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100630 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100631 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100632 if (!value) {
633 goto error;
634 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100635 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100636 lydict_remove(module->ctx, value);
637
638 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200639 goto error;
640 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 break;
642
643 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200644 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200645 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200646 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
647 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200648 continue;
649 }
650
Radek Krejciaf351422015-06-19 14:49:38 +0200651 if (!strcmp(node->name, "require-instance")) {
652 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100653 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200654 goto error;
655 }
656 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200657 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200658 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200659 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200660 type->info.inst.req = -1;
661 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100662 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200663 goto error;
664 }
665 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100666 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200667 goto error;
668 }
Radek Krejciaf351422015-06-19 14:49:38 +0200669 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200671 break;
672
Radek Krejcif2860132015-06-20 12:37:20 +0200673 case LY_TYPE_BINARY:
674 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200675 case LY_TYPE_INT8:
676 case LY_TYPE_INT16:
677 case LY_TYPE_INT32:
678 case LY_TYPE_INT64:
679 case LY_TYPE_UINT8:
680 case LY_TYPE_UINT16:
681 case LY_TYPE_UINT32:
682 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200683 /* RFC 6020 9.2.4 - range */
684
685 /* length and range are actually the same restriction, so process
686 * them by this common code, we just need to differ the name and
687 * structure where the information will be stored
688 */
689 if (type->base == LY_TYPE_BINARY) {
690 restr = &type->info.binary.length;
691 name = "length";
692 } else {
693 restr = &type->info.num.range;
694 name = "range";
695 }
696
Radek Krejci73adb602015-07-02 18:07:40 +0200697 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200698 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
699 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200700 continue;
701 }
702
Radek Krejcif2860132015-06-20 12:37:20 +0200703 if (!strcmp(node->name, name)) {
704 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100705 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200706 goto error;
707 }
708
709 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200710 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100711 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200712 goto error;
713 }
714 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100715 if (!(*restr)) {
716 LOGMEM;
717 goto error;
718 }
Radek Krejcif2860132015-06-20 12:37:20 +0200719 (*restr)->expr = lydict_insert(module->ctx, value, 0);
720
721 /* get possible substatements */
722 if (read_restr_substmt(module->ctx, *restr, node)) {
723 goto error;
724 }
725 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100726 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200727 goto error;
728 }
Radek Krejcif2860132015-06-20 12:37:20 +0200729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200730 break;
731
732 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200733 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200734 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200735 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
736 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200737 continue;
738 }
739
Michal Vasko88c29542015-11-27 14:57:53 +0100740 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200741 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100742 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200743 goto error;
744 }
745
746 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200747 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100748 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200749 if (!type->info.lref.path) {
750 goto error;
751 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100752 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200753 goto error;
754 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200755
Radek Krejcidc4c1412015-06-19 15:39:54 +0200756 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100757 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200758 goto error;
759 }
Radek Krejci73adb602015-07-02 18:07:40 +0200760 }
761
Michal Vasko88c29542015-11-27 14:57:53 +0100762 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100763 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200764 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200765 } else if (type->der->type.der && parent) {
766 for (type_der = &type->der->type; !type_der->info.lref.path && type_der->der; type_der = &type_der->der->type);
767 assert(type_der->info.lref.path && type_der->info.lref.target);
768 /* add pointer to leafref target, only on leaves (not in typedefs) */
769 if (lys_leaf_add_leafref_target(type_der->info.lref.target, (struct lys_node *)type->parent)) {
770 goto error;
771 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200772 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200773 break;
774
775 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200776 /* RFC 6020 9.4.4 - length */
777 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200778 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200779 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200780 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
781 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100782 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200783 continue;
784 }
785
Radek Krejci3733a802015-06-19 13:43:21 +0200786 if (!strcmp(node->name, "length")) {
787 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100788 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200789 goto error;
790 }
791
792 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200793 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100794 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200795 goto error;
796 }
797 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100798 if (!type->info.str.length) {
799 LOGMEM;
800 goto error;
801 }
Radek Krejci3733a802015-06-19 13:43:21 +0200802 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
803
Radek Krejci5fbc9162015-06-19 14:11:11 +0200804 /* get possible sub-statements */
805 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200806 goto error;
807 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100808 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200809 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200810 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200811 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100812 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200813 goto error;
814 }
815 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200816 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200817 if (i) {
818 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100819 if (!type->info.str.patterns) {
820 LOGMEM;
821 goto error;
822 }
Radek Krejci73adb602015-07-02 18:07:40 +0200823 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100824 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200825
Michal Vasko0aee5c12016-06-17 14:27:26 +0200826 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +0200827 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +0200828 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +0200829 goto error;
830 }
Michal Vasko69068852015-07-13 14:34:31 +0200831
Radek Krejci73adb602015-07-02 18:07:40 +0200832 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200833
834 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100835 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200836 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200837 goto error;
838 }
Radek Krejci73adb602015-07-02 18:07:40 +0200839 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200840 }
841 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200842 break;
843
844 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200845 /* RFC 6020 7.4 - type */
846 /* count number of types in union */
847 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200848 LY_TREE_FOR_SAFE(yin->child, next, node) {
849 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
850 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100851 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200852 continue;
853 }
854
Radek Krejcie4c366b2015-07-02 10:11:31 +0200855 if (!strcmp(node->name, "type")) {
856 i++;
857 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100858 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200859 goto error;
860 }
861 }
862
863 if (!i) {
864 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100865 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200866 break;
867 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100868 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200869 goto error;
870 }
871
872 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200873 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100874 if (!type->info.uni.types) {
875 LOGMEM;
876 goto error;
877 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200878 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200879 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100880 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100881 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
882 if (!rc) {
883 type->info.uni.count++;
884
885 /* union's type cannot be empty or leafref */
886 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100887 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100888 rc = -1;
889 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100890 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100891 rc = -1;
892 }
893 }
894 if (rc) {
895 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
896 for (i = 0; i < type->info.uni.count; ++i) {
897 lys_type_free(module->ctx, &type->info.uni.types[i]);
898 }
899 free(type->info.uni.types);
900 type->info.uni.types = NULL;
901 type->info.uni.count = 0;
902
903 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100904 ret = EXIT_FAILURE;
905 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100906 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200907 goto error;
908 }
Michal Vasko88c29542015-11-27 14:57:53 +0100909 }
910 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200911
Michal Vasko88c29542015-11-27 14:57:53 +0100912 case LY_TYPE_BOOL:
913 case LY_TYPE_EMPTY:
914 /* no sub-statement allowed */
915 LY_TREE_FOR(yin->child, node) {
916 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100917 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200918 goto error;
919 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200920 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 break;
922
923 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100924 LOGINT;
925 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200926 }
927
928 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200929
930error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100931 if (type->module_name) {
932 lydict_remove(module->ctx, type->module_name);
933 type->module_name = NULL;
934 }
935 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200936}
937
Michal Vasko0d343d12015-08-24 14:57:36 +0200938/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200940fill_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 +0200941{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100943 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100944 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100947 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 goto error;
949 }
950 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100953 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 goto error;
955 }
Radek Krejcieac35532015-05-31 19:09:15 +0200956
Michal Vasko88c29542015-11-27 14:57:53 +0100957 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200958 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
959 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200960 continue;
961 }
962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100964 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100965 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200966 goto error;
967 }
Michal Vasko88c29542015-11-27 14:57:53 +0100968 /* HACK for unres */
969 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100970 tpdf->type.parent = tpdf;
Radek Krejci48464ed2016-03-17 15:44:09 +0100971 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent)) {
Radek Krejci73adb602015-07-02 18:07:40 +0200972 goto error;
973 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200974 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 } else if (!strcmp(node->name, "default")) {
976 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100977 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200978 goto error;
979 }
980 GETVAL(value, node, "value");
981 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
982 } else if (!strcmp(node->name, "units")) {
983 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100984 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 goto error;
986 }
987 GETVAL(value, node, "name");
988 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
989 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100990 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 goto error;
992 }
993 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200996 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100997 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200998 goto error;
999 }
Radek Krejcieac35532015-05-31 19:09:15 +02001000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001002 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001003 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001004 goto error;
1005 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001009
1010error:
1011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001012 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001013}
1014
Michal Vasko0d343d12015-08-24 14:57:36 +02001015/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001016static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001017fill_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 +02001018{
1019 const char *value;
1020 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001021 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001022
Radek Krejcib05774c2015-06-18 13:52:59 +02001023 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001024 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001025 goto error;
1026 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001027 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001028 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001029
Radek Krejci76512572015-08-04 09:47:08 +02001030 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001031 goto error;
1032 }
1033
1034 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001035 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1036 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001037 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001038 continue;
1039 }
1040
Radek Krejci3cf9e222015-06-18 11:37:50 +02001041 if (!strcmp(child->name, "if-feature")) {
1042 c++;
1043 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001044 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001045 goto error;
1046 }
1047 }
1048
1049 if (c) {
1050 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001051 if (!f->features) {
1052 LOGMEM;
1053 goto error;
1054 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001055 }
Radek Krejci73adb602015-07-02 18:07:40 +02001056 LY_TREE_FOR(yin->child, child) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001057 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001058 f->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001059 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001060 goto error;
1061 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001062 }
1063
Radek Krejci3cf9e222015-06-18 11:37:50 +02001064 return EXIT_SUCCESS;
1065
1066error:
1067
1068 return EXIT_FAILURE;
1069}
1070
Michal Vasko0d343d12015-08-24 14:57:36 +02001071/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072static int
Radek Krejcib8048692015-08-05 13:36:34 +02001073fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001074{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001078 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001079 if (!must->expr) {
1080 goto error;
1081 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001082 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001083 goto error;
1084 }
Radek Krejci800af702015-06-02 13:46:01 +02001085
Radek Krejci41726f92015-06-19 13:11:05 +02001086 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001087
Michal Vasko77dc5652016-02-15 12:32:42 +01001088error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001090}
1091
Radek Krejci581ce772015-11-10 17:22:40 +01001092static int
Michal Vasko88c29542015-11-27 14:57:53 +01001093fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1094 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001095{
1096 int i, j;
1097 const char *value, *vaux;
1098
1099 /* get unique value (list of leafs supposed to be unique */
1100 GETVAL(value, yin, "tag");
1101
1102 /* count the number of unique leafs in the value */
1103 vaux = value;
1104 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001105 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001106 while (isspace(*vaux)) {
1107 vaux++;
1108 }
1109 }
1110 unique->expr_size++;
1111 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001112 if (!unique->expr) {
1113 LOGMEM;
1114 goto error;
1115 }
Radek Krejci581ce772015-11-10 17:22:40 +01001116
1117 for (i = 0; i < unique->expr_size; i++) {
1118 vaux = strpbrk(value, " \t\n");
1119 if (!vaux) {
1120 /* the last token, lydict_insert() will count its size on its own */
1121 vaux = value;
1122 }
1123
1124 /* store token into unique structure */
1125 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1126
1127 /* check that the expression does not repeat */
1128 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001129 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001130 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1131 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001132 goto error;
1133 }
1134 }
1135
1136 /* try to resolve leaf */
1137 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001138 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1139 goto error;
1140 }
Radek Krejci581ce772015-11-10 17:22:40 +01001141 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001142 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001143 goto error;
1144 }
1145 }
1146
1147 /* move to next token */
1148 value = vaux;
1149 while(isspace(*value)) {
1150 value++;
1151 }
1152 }
1153
1154 return EXIT_SUCCESS;
1155
1156error:
1157 return EXIT_FAILURE;
1158}
1159
Michal Vasko0d343d12015-08-24 14:57:36 +02001160/* logs directly
1161 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001162 * type: 0 - min, 1 - max
1163 */
1164static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001165deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001166{
1167 const char *value;
1168 char *endptr;
1169 unsigned long val;
1170 uint32_t *ui32val;
1171
Michal Vaskof7e57d52016-03-07 11:31:09 +01001172 /* del min/max is forbidden */
1173 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001174 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001175 goto error;
1176 }
1177
Radek Krejcieb00f512015-07-01 16:44:58 +02001178 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001179 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001180 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001181 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001182 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001183 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001184 }
Radek Krejci76512572015-08-04 09:47:08 +02001185 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001186 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001187 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001188 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001189 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001190 }
1191 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001192 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1193 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001194 goto error;
1195 }
1196
1197 GETVAL(value, node, "value");
1198 while (isspace(value[0])) {
1199 value++;
1200 }
1201
Radek Krejci0d7b2472016-02-12 11:11:03 +01001202 if (type && !strcmp(value, "unbounded")) {
1203 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001204 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001205 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001206 /* convert it to uint32_t */
1207 errno = 0;
1208 endptr = NULL;
1209 val = strtoul(value, &endptr, 10);
1210 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001211 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001212 goto error;
1213 }
1214 if (type) {
1215 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001216 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001217 } else {
1218 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001219 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001220 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001221 }
1222
1223 if (d->mod == LY_DEVIATE_ADD) {
1224 /* check that there is no current value */
1225 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001226 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1227 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001228 goto error;
1229 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001230 } else if (d->mod == LY_DEVIATE_RPL) {
1231 /* unfortunately, there is no way to check reliably that there
1232 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001233 }
1234
Michal Vaskof7e57d52016-03-07 11:31:09 +01001235 /* add (already checked) and replace */
1236 /* set new value specified in deviation */
1237 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001238
1239 return EXIT_SUCCESS;
1240
1241error:
1242
1243 return EXIT_FAILURE;
1244}
1245
Michal Vasko0d343d12015-08-24 14:57:36 +02001246/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001247static int
Michal Vasko88c29542015-11-27 14:57:53 +01001248fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1249 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001250{
1251 const char *value, **stritem;
1252 struct lyxml_elem *next, *child, *develem;
1253 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001254 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001255 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001256 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001257 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001258 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001259 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001260 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001261 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001262 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001263 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001264 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001265 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001266
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001267 ctx = module->ctx;
1268
Radek Krejcieb00f512015-07-01 16:44:58 +02001269 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001270 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001271 if (!dev->target_name) {
1272 goto error;
1273 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001274
1275 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001276 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1277 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001278 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001279 goto error;
1280 }
Radek Krejcic4283442016-04-22 09:19:27 +02001281 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001282 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1283 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001284 goto error;
1285 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001286 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001287
1288 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001289 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1290 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001291 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001292 continue;
1293 }
1294
Radek Krejcieb00f512015-07-01 16:44:58 +02001295 if (!strcmp(child->name, "description")) {
1296 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001297 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001298 goto error;
1299 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001300 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001301 if (!dev->dsc) {
1302 goto error;
1303 }
1304 } else if (!strcmp(child->name, "reference")) {
1305 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001306 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001307 goto error;
1308 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001309 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001310 if (!dev->ref) {
1311 goto error;
1312 }
1313 } else if (!strcmp(child->name, "deviate")) {
1314 c_dev++;
1315
Michal Vasko345da0a2015-12-02 10:35:55 +01001316 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001317 * further processed later
1318 */
1319 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001320
Radek Krejcieb00f512015-07-01 16:44:58 +02001321 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001322 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001323 goto error;
1324 }
1325
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001326 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001327 }
1328
1329 if (c_dev) {
1330 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001331 if (!dev->deviate) {
1332 LOGMEM;
1333 goto error;
1334 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001335 }
1336
1337 LY_TREE_FOR(yin->child, develem) {
1338 /* init */
1339 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001340 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001341 c_must = 0;
1342 c_uniq = 0;
1343
1344 /* get deviation type */
1345 GETVAL(value, develem, "value");
1346 if (!strcmp(value, "not-supported")) {
1347 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1348 /* no property expected in this case */
1349 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001350 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001351 goto error;
1352 }
1353
Radek Krejci5b917642015-07-02 09:03:13 +02001354 /* and neither any other deviate statement is expected,
1355 * not-supported deviation must be the only deviation of the target
1356 */
1357 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001358 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1359 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001360 goto error;
1361 }
1362
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001363 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001364 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1365 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1366 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001367 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1368 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001369 goto error;
1370 }
1371 }
1372 }
Radek Krejci5b917642015-07-02 09:03:13 +02001373
Michal Vaskoff006c12016-02-17 11:15:19 +01001374 /* unlink and store the original node */
1375 lys_node_unlink(dev_target);
1376 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001377
Radek Krejci5b917642015-07-02 09:03:13 +02001378 dev->deviate_size = 1;
1379 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001380 } else if (!strcmp(value, "add")) {
1381 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1382 } else if (!strcmp(value, "replace")) {
1383 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1384 } else if (!strcmp(value, "delete")) {
1385 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1386 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001387 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001388 goto error;
1389 }
1390 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001391 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001392
Michal Vaskoff006c12016-02-17 11:15:19 +01001393 /* store a shallow copy of the original node */
1394 if (!dev->orig_node) {
1395 memset(&tmp_unres, 0, sizeof tmp_unres);
1396 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1397 /* just to be safe */
1398 if (tmp_unres.count) {
1399 LOGINT;
1400 goto error;
1401 }
1402 }
1403
Radek Krejcieb00f512015-07-01 16:44:58 +02001404 /* process deviation properties */
1405 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001406 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1407 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001408 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001409 continue;
1410 }
1411
Radek Krejcieb00f512015-07-01 16:44:58 +02001412 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001413 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001414 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001415 goto error;
1416 }
1417
1418 /* for we deviate from RFC 6020 and allow config property even it is/is not
1419 * specified in the target explicitly since config property inherits. So we expect
1420 * that config is specified in every node. But for delete, we check that the value
1421 * is the same as here in deviation
1422 */
1423 GETVAL(value, child, "value");
1424 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001425 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001426 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001427 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001428 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001429 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001430 goto error;
1431 }
1432
1433 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001434 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001435 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001436 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001437 } else { /* add and replace are the same in this case */
1438 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001439 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001440
1441 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001442 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001443 }
1444 } else if (!strcmp(child->name, "default")) {
1445 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001446 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001447 goto error;
1448 }
1449 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001450 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001451
Michal Vasko60f4b452016-02-12 11:02:55 +01001452 if (dev_target->nodetype == LYS_CHOICE) {
1453 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001454
1455 if (d->mod == LY_DEVIATE_ADD) {
1456 /* check that there is no current value */
1457 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001458 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1459 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001460 goto error;
1461 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001462 /* check collision with mandatory */
1463 if (choice->flags & LYS_MAND_TRUE) {
1464 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1465 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1466 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1467 goto error;
1468 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001469 } else if (d->mod == LY_DEVIATE_RPL) {
1470 /* check that there was a value before */
1471 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001472 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1473 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001474 goto error;
1475 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001476 }
1477
Michal Vasko3edeaf72016-02-11 13:17:43 +01001478 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001479 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001480 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001481 goto error;
1482 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001483 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001484 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001485 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1486 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001487 goto error;
1488 }
1489 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001490 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001491 if (!choice->dflt) {
1492 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001493 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001494 goto error;
1495 }
1496 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001497 } else if (dev_target->nodetype == LYS_LEAF) {
1498 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001499
1500 if (d->mod == LY_DEVIATE_ADD) {
1501 /* check that there is no current value */
1502 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001503 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1504 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001505 goto error;
1506 }
Radek Krejci841ec082016-04-05 13:05:17 +02001507 /* check collision with mandatory */
1508 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001509 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001510 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001511 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001512 goto error;
1513 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001514 }
1515
1516 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001517 if (!leaf->dflt || !ly_strequal(leaf->dflt, d->dflt, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001518 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1519 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001520 goto error;
1521 }
1522 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001523 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001524 leaf->dflt = NULL;
1525 } else { /* add (already checked) and replace */
1526 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001527 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001528
1529 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001530 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001531
1532 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1533 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1534 if (!leaf_dflt_check) {
1535 LOGMEM;
1536 goto error;
1537 }
1538 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001539 }
1540 } else {
1541 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001542 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1543 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 goto error;
1545 }
1546 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001547 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001548 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001549 goto error;
1550 }
1551
1552 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001553 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001554 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1555 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001556 goto error;
1557 }
1558
1559 GETVAL(value, child, "value");
1560 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001561 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001563 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001564 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001565 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 goto error;
1567 }
1568
1569 if (d->mod == LY_DEVIATE_ADD) {
1570 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001571 if (dev_target->flags & LYS_MAND_MASK) {
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, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001574 goto error;
1575 }
Radek Krejci841ec082016-04-05 13:05:17 +02001576 /* check collision with default-stmt */
1577 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001578 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001579 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001580 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001581 goto error;
1582 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001583
Michal Vasko21be1b32016-03-07 12:31:34 +01001584 dev_target->flags |= d->flags & LYS_MAND_MASK;
1585 } else if (d->mod == LY_DEVIATE_RPL) {
1586 /* check that there was a value before */
1587 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001588 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1589 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001590 goto error;
1591 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001592
Michal Vasko21be1b32016-03-07 12:31:34 +01001593 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001594 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001595 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001596 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001597 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001598 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001599 }
1600 } else if (!strcmp(child->name, "min-elements")) {
1601 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001602 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001603 goto error;
1604 }
1605 f_min = 1;
1606
Michal Vasko60f4b452016-02-12 11:02:55 +01001607 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001608 goto error;
1609 }
1610 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001611 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001612 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001613 goto error;
1614 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001615 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001616
Michal Vasko60f4b452016-02-12 11:02:55 +01001617 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001618 goto error;
1619 }
1620 } else if (!strcmp(child->name, "must")) {
1621 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001622 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001623 continue;
1624 } else if (!strcmp(child->name, "type")) {
1625 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001626 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001627 goto error;
1628 }
1629
Michal Vaskof7e57d52016-03-07 11:31:09 +01001630 /* add, del type is forbidden */
1631 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001632 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001633 goto error;
1634 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001635 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001636 goto error;
1637 }
1638
Radek Krejcieb00f512015-07-01 16:44:58 +02001639 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001640 if (dev_target->nodetype == LYS_LEAF) {
1641 t = &((struct lys_node_leaf *)dev_target)->type;
1642 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1643 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001645 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1646 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 goto error;
1648 }
1649
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001651 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001652 /* HACK for unres */
1653 t->der = (struct lys_tpdf *)child;
Radek Krejci48464ed2016-03-17 15:44:09 +01001654 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001655 goto error;
1656 }
1657 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001658
1659 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1660 if (dev_target->nodetype == LYS_LEAF) {
1661 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1662 if (!leaf_dflt_check) {
1663 LOGMEM;
1664 goto error;
1665 }
1666 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1667 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001668 } else if (!strcmp(child->name, "unique")) {
1669 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001670 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 continue;
1672 } else if (!strcmp(child->name, "units")) {
1673 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001674 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001675 goto error;
1676 }
1677
1678 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001679 if (dev_target->nodetype == LYS_LEAFLIST) {
1680 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1681 } else if (dev_target->nodetype == LYS_LEAF) {
1682 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001683 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001684 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1685 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001686 goto error;
1687 }
1688
1689 /* get units value */
1690 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001691 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001692
1693 /* apply to target */
1694 if (d->mod == LY_DEVIATE_ADD) {
1695 /* check that there is no current value */
1696 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001697 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1698 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001699 goto error;
1700 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001701
Michal Vasko21be1b32016-03-07 12:31:34 +01001702 *stritem = lydict_insert(ctx, value, 0);
1703 } else if (d->mod == LY_DEVIATE_RPL) {
1704 /* check that there was a value before */
1705 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001706 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1707 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001708 goto error;
1709 }
1710
1711 lydict_remove(ctx, *stritem);
1712 *stritem = lydict_insert(ctx, value, 0);
1713 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001714 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001715 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001716 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1717 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001718 goto error;
1719 }
1720 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001721 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001722 }
1723 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001724 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 goto error;
1726 }
1727
Michal Vasko88c29542015-11-27 14:57:53 +01001728 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 }
1730
1731 if (c_must) {
1732 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001733 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001734 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001735 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1736 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001737 break;
Radek Krejci76512572015-08-04 09:47:08 +02001738 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001739 trg_must = &((struct lys_node_container *)dev_target)->must;
1740 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 break;
Radek Krejci76512572015-08-04 09:47:08 +02001742 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001743 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1744 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001745 break;
Radek Krejci76512572015-08-04 09:47:08 +02001746 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001747 trg_must = &((struct lys_node_list *)dev_target)->must;
1748 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001749 break;
Radek Krejci76512572015-08-04 09:47:08 +02001750 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001751 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1752 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001753 break;
1754 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001755 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1756 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001757 goto error;
1758 }
1759
1760 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001761 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001762 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001763 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001764 } else if (d->mod == LY_DEVIATE_ADD) {
1765 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001766 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001767 if (!d->must) {
1768 LOGMEM;
1769 goto error;
1770 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001772 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001773 d->must_size = c_must;
1774 } else { /* LY_DEVIATE_DEL */
1775 d->must = calloc(c_must, sizeof *d->must);
1776 }
Michal Vasko253035f2015-12-17 16:58:13 +01001777 if (!d->must) {
1778 LOGMEM;
1779 goto error;
1780 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001781 }
1782 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001783 /* replace unique is forbidden */
1784 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001785 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001786 goto error;
1787 }
1788
Radek Krejcieb00f512015-07-01 16:44:58 +02001789 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001790 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001791 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1792 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001793 goto error;
1794 }
1795
Michal Vasko60f4b452016-02-12 11:02:55 +01001796 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001797 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001799 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001800 list->unique = d->unique;
1801 d->unique = &list->unique[list->unique_size];
1802 d->unique_size = c_uniq;
1803 } else { /* LY_DEVIATE_DEL */
1804 d->unique = calloc(c_uniq, sizeof *d->unique);
1805 }
Michal Vasko253035f2015-12-17 16:58:13 +01001806 if (!d->unique) {
1807 LOGMEM;
1808 goto error;
1809 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001810 }
1811
1812 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001813 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 if (!strcmp(child->name, "must")) {
1815 if (d->mod == LY_DEVIATE_DEL) {
1816 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1817 goto error;
1818 }
1819
1820 /* find must to delete, we are ok with just matching conditions */
1821 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001822 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001824 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 /* ... and maintain the array */
1826 (*trg_must_size)--;
1827 if (i != *trg_must_size) {
1828 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1829 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1830 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1831 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1832 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1833 }
1834 if (!(*trg_must_size)) {
1835 free(*trg_must);
1836 *trg_must = NULL;
1837 } else {
1838 (*trg_must)[*trg_must_size].expr = NULL;
1839 (*trg_must)[*trg_must_size].dsc = NULL;
1840 (*trg_must)[*trg_must_size].ref = NULL;
1841 (*trg_must)[*trg_must_size].eapptag = NULL;
1842 (*trg_must)[*trg_must_size].emsg = NULL;
1843 }
1844
1845 i = -1; /* set match flag */
1846 break;
1847 }
1848 }
1849 d->must_size++;
1850 if (i != -1) {
1851 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001852 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001853 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001854 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 goto error;
1856 }
1857 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001858 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1859 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001860 goto error;
1861 }
1862 (*trg_must_size)++;
1863 }
1864 } else if (!strcmp(child->name, "unique")) {
1865 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001866 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001867 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001868 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001869 goto error;
1870 }
1871
1872 /* find unique structures to delete */
1873 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001874 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001875 continue;
1876 }
1877
Radek Krejci581ce772015-11-10 17:22:40 +01001878 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001879 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001880 break;
1881 }
1882 }
1883
Radek Krejci581ce772015-11-10 17:22:40 +01001884 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001885 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001886 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001887 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001888 }
1889 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001890 /* ... and maintain the array */
1891 list->unique_size--;
1892 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001893 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1894 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001895 }
1896
1897 if (!list->unique_size) {
1898 free(list->unique);
1899 list->unique = NULL;
1900 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001901 list->unique[list->unique_size].expr_size = 0;
1902 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001903 }
1904
1905 i = -1; /* set match flag */
1906 break;
1907 }
1908 }
1909
1910 d->unique_size++;
1911 if (i != -1) {
1912 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001913 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1914 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001915 goto error;
1916 }
1917 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001918 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001919 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001920 list->unique_size++;
1921 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 goto error;
1923 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001924 }
1925 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001926 }
1927 }
1928
Michal Vasko43a1feb2016-03-07 12:03:02 +01001929 /* now check whether default value, if any, matches the type */
1930 for (i = 0; i < leaf_dflt_check_count; ++i) {
1931 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001932 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 +01001933 if (rc == -1) {
1934 goto error;
1935 } else if (rc == EXIT_FAILURE) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001936 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1937 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 +01001938 goto error;
1939 }
1940 }
1941 }
1942 free(leaf_dflt_check);
1943
Radek Krejcieb00f512015-07-01 16:44:58 +02001944 return EXIT_SUCCESS;
1945
1946error:
Michal Vasko34867132016-03-11 10:26:38 +01001947 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001948 return EXIT_FAILURE;
1949}
1950
Michal Vasko0d343d12015-08-24 14:57:36 +02001951/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001952static int
Radek Krejcib8048692015-08-05 13:36:34 +02001953fill_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 +02001954 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001955{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001956 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001957 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001958 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001959 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001960
Michal Vasko591e0b22015-08-13 13:53:43 +02001961 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001963 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02001964 if (!aug->target_name) {
1965 goto error;
1966 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001967 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001968
Michal Vasko1d87a922015-08-21 12:57:16 +02001969 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001970 goto error;
1971 }
1972
1973 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001974 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1975 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001976 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001977 continue;
1978 }
1979
Radek Krejci3cf9e222015-06-18 11:37:50 +02001980 if (!strcmp(child->name, "if-feature")) {
1981 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001982 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001983 } else if (!strcmp(child->name, "when")) {
1984 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001985 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001986 goto error;
1987 }
1988
1989 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001990 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001991 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001992 goto error;
1993 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001994 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001996
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997 /* check allowed data sub-statements */
1998 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001999 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002000 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002003 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002004 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002005 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002007 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002009 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002010 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002013 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002014 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002015 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002016 goto error;
2017 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002018
Radek Krejci1d82ef62015-08-07 14:44:40 +02002019 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002020 goto error;
2021 }
2022
Radek Krejci1d82ef62015-08-07 14:44:40 +02002023 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002024 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002025 }
2026
2027 if (c) {
2028 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002029 if (!aug->features) {
2030 LOGMEM;
2031 goto error;
2032 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002033 }
2034
2035 LY_TREE_FOR_SAFE(yin->child, next, child) {
2036 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002037 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002038 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002039 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002040 goto error;
2041 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002042 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002043 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002044 }
2045
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002047 * connected to the tree and adjusted (if possible right now).
2048 * However, if this is augment in a uses, it gets resolved
2049 * when the uses does and cannot be resolved now for sure
2050 * (the grouping was not yet copied into uses).
2051 */
2052 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002053 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002054 goto error;
2055 }
Michal Vasko49291b32015-08-06 09:49:41 +02002056 }
Radek Krejci106efc02015-06-10 14:36:27 +02002057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002059
2060error:
2061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002063}
2064
Michal Vasko0d343d12015-08-24 14:57:36 +02002065/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066static int
Michal Vasko0d204592015-10-07 09:50:04 +02002067fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002068{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 struct lyxml_elem *sub, *next;
2070 const char *value;
2071 char *endptr;
2072 int f_mand = 0, f_min = 0, f_max = 0;
2073 int c_must = 0;
2074 int r;
2075 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002076
Radek Krejci76512572015-08-04 09:47:08 +02002077 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 goto error;
2079 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002080
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002081 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002082 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002083 if (!rfn->target_name) {
2084 goto error;
2085 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002088 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2089 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002090 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002091 continue;
2092 }
2093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 /* limited applicability */
2095 if (!strcmp(sub->name, "default")) {
2096 /* leaf or choice */
2097 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002098 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 goto error;
2100 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 /* check possibility of statements combination */
2103 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002104 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002106 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2107 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 goto error;
2109 }
2110 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002111 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 GETVAL(value, sub, "value");
2115 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2116 } else if (!strcmp(sub->name, "mandatory")) {
2117 /* leaf, choice or anyxml */
2118 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002119 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 goto error;
2121 }
2122 /* just checking the flags in leaf is not sufficient, we would allow
2123 * multiple mandatory statements with the "false" value
2124 */
2125 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 /* check possibility of statements combination */
2128 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002129 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002131 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2132 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 goto error;
2134 }
2135 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002136 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 GETVAL(value, sub, "value");
2140 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002141 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002143 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002145 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 goto error;
2147 }
2148 } else if (!strcmp(sub->name, "min-elements")) {
2149 /* list or leaf-list */
2150 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002151 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 goto error;
2153 }
2154 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 /* check possibility of statements combination */
2157 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002158 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002160 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2161 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 goto error;
2163 }
2164 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002165 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 GETVAL(value, sub, "value");
2169 while (isspace(value[0])) {
2170 value++;
2171 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 /* convert it to uint32_t */
2174 errno = 0;
2175 endptr = NULL;
2176 val = strtoul(value, &endptr, 10);
2177 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002178 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 goto error;
2180 }
2181 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002182 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 } else if (!strcmp(sub->name, "max-elements")) {
2184 /* list or leaf-list */
2185 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002186 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 goto error;
2188 }
2189 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 /* check possibility of statements combination */
2192 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002193 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002195 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2196 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 goto error;
2198 }
2199 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002200 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 GETVAL(value, sub, "value");
2204 while (isspace(value[0])) {
2205 value++;
2206 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002207
Radek Krejci0d7b2472016-02-12 11:11:03 +01002208 if (!strcmp(value, "unbounded")) {
2209 rfn->mod.list.max = 0;
2210 } else {
2211 /* convert it to uint32_t */
2212 errno = 0;
2213 endptr = NULL;
2214 val = strtoul(value, &endptr, 10);
2215 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002216 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002217 goto error;
2218 }
2219 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002221 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 } else if (!strcmp(sub->name, "presence")) {
2223 /* container */
2224 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002225 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 goto error;
2227 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 /* check possibility of statements combination */
2230 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002231 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002233 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2234 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 goto error;
2236 }
2237 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002238 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 GETVAL(value, sub, "value");
2242 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2243 } else if (!strcmp(sub->name, "must")) {
2244 /* leaf-list, list, container or anyxml */
2245 /* check possibility of statements combination */
2246 if (rfn->target_type) {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002247 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002249 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2250 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 goto error;
2252 }
2253 } else {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002254 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002258 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002261 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 goto error;
2263 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002264
Michal Vasko345da0a2015-12-02 10:35:55 +01002265 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 /* process nodes with cardinality of 0..n */
2269 if (c_must) {
2270 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002271 if (!rfn->must) {
2272 LOGMEM;
2273 goto error;
2274 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 }
Radek Krejci73adb602015-07-02 18:07:40 +02002276 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002277 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2278 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002279 if (r) {
2280 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002284 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002285
2286error:
2287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002289}
2290
Michal Vasko0d343d12015-08-24 14:57:36 +02002291/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292static int
Radek Krejcib8048692015-08-05 13:36:34 +02002293fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002294{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 struct lyxml_elem *child;
2296 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002299 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2300 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002301 continue;
2302 }
2303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 if (!strcmp(child->name, "prefix")) {
2305 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002306 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 goto error;
2308 }
2309 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2310 } else if (!strcmp(child->name, "revision-date")) {
2311 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002312 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2313 goto error;
2314 } else if (!imp->prefix) {
2315 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2316 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2317 "The \"prefix\" statement is expected before the \"revision-date\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 goto error;
2319 }
2320 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002321 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 goto error;
2323 }
2324 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2325 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002326 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 goto error;
2328 }
2329 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 /* check mandatory information */
2332 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002333 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 goto error;
2335 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002338
Pavol Vicane994fda2016-03-22 10:47:58 +01002339 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002340
2341error:
2342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002344}
2345
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002346/* logs directly
2347 * returns:
2348 * 0 - inc successfully filled
2349 * -1 - error, inc is cleaned
2350 * 1 - duplication, ignore the inc structure, inc is cleaned
2351 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002352static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002353fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2354 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002355{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 struct lyxml_elem *child;
2357 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002360 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2361 /* garbage */
2362 continue;
2363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 if (!strcmp(child->name, "revision-date")) {
2365 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002366 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 goto error;
2368 }
2369 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002370 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 goto error;
2372 }
2373 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2374 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002375 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002376 goto error;
2377 }
2378 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002381
Pavol Vican0adf01d2016-03-22 12:29:33 +01002382 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002383
2384error:
2385
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002386 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002387}
2388
Michal Vasko0d343d12015-08-24 14:57:36 +02002389/* logs directly
2390 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002391 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002392 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002393 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002394 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395static int
Radek Krejcib8048692015-08-05 13:36:34 +02002396read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002397 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002398{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399 const char *value;
2400 struct lyxml_elem *sub, *next;
2401 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002404 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002407 if (opt & OPT_IDENT) {
2408 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002409 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 goto error;
2411 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002412 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002414
Radek Krejci6764bb32015-07-03 15:16:04 +02002415 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002416 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002417 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002418 }
2419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 /* process local parameters */
2421 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002422 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002423 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002424 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002425 continue;
2426 }
2427 if (strcmp(sub->ns->value, LY_NSYIN)) {
2428 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002429 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002430 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002431 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002432 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002433 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002434 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002435 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002436 goto error;
2437 }
2438 }
2439
2440 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002441 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002442 continue;
2443 }
2444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002446 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 goto error;
2449 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002450 node->dsc = read_yin_subnode(ctx, sub, "text");
2451 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002452 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 }
2454 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002455 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002456 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002457 goto error;
2458 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 node->ref = read_yin_subnode(ctx, sub, "text");
2460 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002461 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 }
2463 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002464 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002465 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 goto error;
2467 }
2468 GETVAL(value, sub, "value");
2469 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002470 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002472 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002474 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002476 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002477 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 }
2479 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002480 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002481 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 goto error;
2483 }
2484 GETVAL(value, sub, "value");
2485 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002486 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002488 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002490 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002491 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002493 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002495 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 continue;
2497 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002498 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002500
Radek Krejci1d82ef62015-08-07 14:44:40 +02002501 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002502 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002503 if (parent && (parent->flags & LYS_CONFIG_R)) {
2504 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 } else {
2506 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002507 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 }
2509 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002512
2513error:
2514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002515 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002516}
2517
Michal Vasko0d343d12015-08-24 14:57:36 +02002518/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002519static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002520read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002521{
Radek Krejci76512572015-08-04 09:47:08 +02002522 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002523 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002524 const char *value;
2525
2526 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002527 if (!retval) {
2528 LOGMEM;
2529 return NULL;
2530 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002531
2532 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002533 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002534 if (!retval->cond) {
2535 goto error;
2536 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002537 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002538 goto error;
2539 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002540
Radek Krejci73adb602015-07-02 18:07:40 +02002541 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002542 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2543 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002544 continue;
2545 }
2546
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002547 if (!strcmp(child->name, "description")) {
2548 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002549 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002550 goto error;
2551 }
2552 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2553 if (!retval->dsc) {
2554 goto error;
2555 }
2556 } else if (!strcmp(child->name, "reference")) {
2557 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002558 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002559 goto error;
2560 }
2561 retval->ref = read_yin_subnode(module->ctx, child, "text");
2562 if (!retval->ref) {
2563 goto error;
2564 }
2565 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002566 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002567 goto error;
2568 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002569 }
2570
2571 return retval;
2572
2573error:
2574
Michal Vasko0308dd62015-10-07 09:14:40 +02002575 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002576 return NULL;
2577}
2578
Michal Vasko0d343d12015-08-24 14:57:36 +02002579/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002580static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002581read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2582 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002583{
Michal Vasko29fc0182015-08-24 15:02:39 +02002584 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002585 struct lys_node_case *cs;
2586 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002587 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002588
Radek Krejcie867c852015-08-27 09:52:34 +02002589 /* init */
2590 memset(&root, 0, sizeof root);
2591
Radek Krejci1d82ef62015-08-07 14:44:40 +02002592 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002593 if (!cs) {
2594 LOGMEM;
2595 return NULL;
2596 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002597 cs->nodetype = LYS_CASE;
2598 cs->prev = (struct lys_node *)cs;
2599 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002600
Radek Krejci6a113852015-07-03 16:04:20 +02002601 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 goto error;
2603 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002604
Radek Krejcia9544502015-08-14 08:24:29 +02002605 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2606
Michal Vasko3a0043f2015-08-12 12:11:30 +02002607 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002608 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002609 goto error;
2610 }
2611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002612 /* process choice's specific children */
2613 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002614 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2615 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002616 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002617 continue;
2618 }
2619
Michal Vasko29fc0182015-08-24 15:02:39 +02002620 if (!strcmp(sub->name, "container") ||
2621 !strcmp(sub->name, "leaf-list") ||
2622 !strcmp(sub->name, "leaf") ||
2623 !strcmp(sub->name, "list") ||
2624 !strcmp(sub->name, "uses") ||
2625 !strcmp(sub->name, "choice") ||
2626 !strcmp(sub->name, "anyxml")) {
2627
Michal Vaskof3930de2015-10-22 12:03:59 +02002628 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002629 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002630 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002631 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002632 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002633 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002634 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002635 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002636 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002637 goto error;
2638 }
2639
Radek Krejci1d82ef62015-08-07 14:44:40 +02002640 cs->when = read_yin_when(module, sub);
2641 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002642 goto error;
2643 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002644
Michal Vasko345da0a2015-12-02 10:35:55 +01002645 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002647 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002650 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002651
Radek Krejci3cf9e222015-06-18 11:37:50 +02002652 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002653 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002654 if (!cs->features) {
2655 LOGMEM;
2656 goto error;
2657 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002658 }
Radek Krejci73adb602015-07-02 18:07:40 +02002659 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002660 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002661 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002662 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002663 goto error;
2664 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 }
Radek Krejcib388c152015-06-04 17:03:03 +02002666
Michal Vasko29fc0182015-08-24 15:02:39 +02002667 /* last part - process data nodes */
2668 LY_TREE_FOR_SAFE(root.child, next, sub) {
2669 if (!strcmp(sub->name, "container")) {
2670 node = read_yin_container(module, retval, sub, resolve, unres);
2671 } else if (!strcmp(sub->name, "leaf-list")) {
2672 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2673 } else if (!strcmp(sub->name, "leaf")) {
2674 node = read_yin_leaf(module, retval, sub, resolve, unres);
2675 } else if (!strcmp(sub->name, "list")) {
2676 node = read_yin_list(module, retval, sub, resolve, unres);
2677 } else if (!strcmp(sub->name, "choice")) {
2678 node = read_yin_choice(module, retval, sub, resolve, unres);
2679 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002680 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02002681 } else if (!strcmp(sub->name, "anyxml")) {
2682 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2683 }
2684 if (!node) {
2685 goto error;
2686 }
2687
Michal Vasko345da0a2015-12-02 10:35:55 +01002688 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002689 }
2690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002692
2693error:
2694
Michal Vasko29fc0182015-08-24 15:02:39 +02002695 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002696 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002697 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002698 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002701}
2702
Michal Vasko0d343d12015-08-24 14:57:36 +02002703/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002704static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002705read_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 +02002706{
Radek Krejci629cdef2016-06-06 15:06:36 +02002707 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002708 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002709 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002710 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02002711 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02002712 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002715 if (!choice) {
2716 LOGMEM;
2717 return NULL;
2718 }
Radek Krejci76512572015-08-04 09:47:08 +02002719 choice->nodetype = LYS_CHOICE;
2720 choice->prev = (struct lys_node *)choice;
2721 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002722
Michal Vaskoe0c59842015-09-24 13:52:20 +02002723 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2724 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 goto error;
2726 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002727
Radek Krejcia9544502015-08-14 08:24:29 +02002728 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2729
Michal Vasko3a0043f2015-08-12 12:11:30 +02002730 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002731 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002732 goto error;
2733 }
2734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 /* process choice's specific children */
2736 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002737 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2738 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002739 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002740 continue;
2741 }
2742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002744 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 goto error;
2746 }
2747 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 goto error;
2750 }
2751 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002752 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 goto error;
2754 }
2755 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002756 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 goto error;
2758 }
2759 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002760 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 goto error;
2762 }
2763 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002764 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 goto error;
2766 }
2767 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02002768 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002769 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002770 goto error;
2771 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002772 dflt = sub;
2773 lyxml_unlink_elem(ctx, dflt, 0);
2774
Radek Krejcif9a312c2016-06-06 15:14:30 +02002775 continue;
2776 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
2777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002778 } else if (!strcmp(sub->name, "mandatory")) {
2779 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002780 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 goto error;
2782 }
2783 /* just checking the flags in leaf is not sufficient, we would allow
2784 * multiple mandatory statements with the "false" value
2785 */
2786 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 GETVAL(value, sub, "value");
2789 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002790 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002791 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002792 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002793 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002794 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002795 goto error;
2796 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002797 } else if (!strcmp(sub->name, "when")) {
2798 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002799 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002800 goto error;
2801 }
2802
2803 choice->when = read_yin_when(module, sub);
2804 if (!choice->when) {
2805 goto error;
2806 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002807 } else if (!strcmp(sub->name, "if-feature")) {
2808 c_ftrs++;
2809
Michal Vasko345da0a2015-12-02 10:35:55 +01002810 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002811 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002813 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002815 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002816
Radek Krejci1d82ef62015-08-07 14:44:40 +02002817 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002818 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002820
Radek Krejci3cf9e222015-06-18 11:37:50 +02002821 if (c_ftrs) {
2822 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002823 if (!choice->features) {
2824 LOGMEM;
2825 goto error;
2826 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002827 }
2828
Radek Krejci73adb602015-07-02 18:07:40 +02002829 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002830 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002831 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002832 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002833 goto error;
2834 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002835 }
2836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02002838 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002839 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2840 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 goto error;
2842 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02002845 if (dflt) {
2846 GETVAL(value, dflt, "value");
2847 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002848 goto error;
2849 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002850 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002851 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002854
2855error:
2856
Radek Krejci629cdef2016-06-06 15:06:36 +02002857 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002858 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002861}
2862
Michal Vasko0d343d12015-08-24 14:57:36 +02002863/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002864static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002865read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002866 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002867{
Radek Krejci76512572015-08-04 09:47:08 +02002868 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002869 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002870 struct lyxml_elem *sub, *next;
2871 const char *value;
2872 int r;
2873 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002874 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002876 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002877 if (!anyxml) {
2878 LOGMEM;
2879 return NULL;
2880 }
Radek Krejci76512572015-08-04 09:47:08 +02002881 anyxml->nodetype = LYS_ANYXML;
2882 anyxml->prev = (struct lys_node *)anyxml;
2883 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002884
Michal Vaskoe0c59842015-09-24 13:52:20 +02002885 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2886 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002887 goto error;
2888 }
Radek Krejci863c2852015-06-03 15:47:11 +02002889
Radek Krejcia9544502015-08-14 08:24:29 +02002890 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002891
Radek Krejcic4283442016-04-22 09:19:27 +02002892 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002893 goto error;
2894 }
2895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002896 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002897 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2898 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002899 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002900 continue;
2901 }
2902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002903 if (!strcmp(sub->name, "mandatory")) {
2904 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002905 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 goto error;
2907 }
2908 /* just checking the flags in leaf is not sufficient, we would allow
2909 * multiple mandatory statements with the "false" value
2910 */
2911 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 GETVAL(value, sub, "value");
2914 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002915 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002916 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002917 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002918 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002919 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 goto error;
2921 }
2922 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002923 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002924 } else if (!strcmp(sub->name, "when")) {
2925 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002926 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002927 goto error;
2928 }
2929
2930 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002931 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002932 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002933 goto error;
2934 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002935 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 } else if (!strcmp(sub->name, "must")) {
2937 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002938 } else if (!strcmp(sub->name, "if-feature")) {
2939 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002940
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002941 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002942 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 }
2945 }
Radek Krejci863c2852015-06-03 15:47:11 +02002946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 /* middle part - process nodes with cardinality of 0..n */
2948 if (c_must) {
2949 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002950 if (!anyxml->must) {
2951 LOGMEM;
2952 goto error;
2953 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002954 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002955 if (c_ftrs) {
2956 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002957 if (!anyxml->features) {
2958 LOGMEM;
2959 goto error;
2960 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002961 }
Radek Krejci863c2852015-06-03 15:47:11 +02002962
Radek Krejci73adb602015-07-02 18:07:40 +02002963 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002965 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2966 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 if (r) {
2968 goto error;
2969 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002970 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002971 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002972 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002973 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002974 goto error;
2975 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002976 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 }
Radek Krejci863c2852015-06-03 15:47:11 +02002978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002980
2981error:
2982
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002983 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02002984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002986}
2987
Michal Vasko0d343d12015-08-24 14:57:36 +02002988/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002989static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002990read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002991 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002992{
Radek Krejci76512572015-08-04 09:47:08 +02002993 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002994 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002995 struct lyxml_elem *sub, *next;
2996 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01002997 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002998 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003001 if (!leaf) {
3002 LOGMEM;
3003 return NULL;
3004 }
Radek Krejci76512572015-08-04 09:47:08 +02003005 leaf->nodetype = LYS_LEAF;
3006 leaf->prev = (struct lys_node *)leaf;
3007 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003008
Michal Vaskoe0c59842015-09-24 13:52:20 +02003009 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3010 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 goto error;
3012 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003013
Radek Krejcia9544502015-08-14 08:24:29 +02003014 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003015
Radek Krejcic4283442016-04-22 09:19:27 +02003016 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003017 goto error;
3018 }
3019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003021 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3022 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003023 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003024 continue;
3025 }
3026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003028 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003029 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 goto error;
3031 }
Michal Vasko88c29542015-11-27 14:57:53 +01003032 /* HACK for unres */
3033 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003034 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci08a11052016-06-13 15:14:30 +02003035 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003036 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 goto error;
3038 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003039 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003040 } else if (!strcmp(sub->name, "default")) {
3041 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003042 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 goto error;
3044 }
3045 GETVAL(value, sub, "value");
3046 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3047 } else if (!strcmp(sub->name, "units")) {
3048 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003049 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 goto error;
3051 }
3052 GETVAL(value, sub, "name");
3053 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3054 } else if (!strcmp(sub->name, "mandatory")) {
3055 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003056 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 goto error;
3058 }
3059 /* just checking the flags in leaf is not sufficient, we would allow
3060 * multiple mandatory statements with the "false" value
3061 */
3062 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 GETVAL(value, sub, "value");
3065 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003066 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003067 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003068 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003069 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003070 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 goto error;
3072 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003073 } else if (!strcmp(sub->name, "when")) {
3074 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003075 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003076 goto error;
3077 }
3078
3079 leaf->when = read_yin_when(module, sub);
3080 if (!leaf->when) {
3081 goto error;
3082 }
3083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003085 c_must++;
3086 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003087 } else if (!strcmp(sub->name, "if-feature")) {
3088 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003092 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003095
Michal Vasko88c29542015-11-27 14:57:53 +01003096 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003097 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003100 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003101 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 goto error;
3103 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003104 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003105 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003106 goto error;
3107 }
Radek Krejci841ec082016-04-05 13:05:17 +02003108 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003109 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003110 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003111 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003112 goto error;
3113 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003114 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 /* middle part - process nodes with cardinality of 0..n */
3117 if (c_must) {
3118 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003119 if (!leaf->must) {
3120 LOGMEM;
3121 goto error;
3122 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003124 if (c_ftrs) {
3125 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003126 if (!leaf->features) {
3127 LOGMEM;
3128 goto error;
3129 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003130 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003131
Radek Krejci73adb602015-07-02 18:07:40 +02003132 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003134 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3135 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 if (r) {
3137 goto error;
3138 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003139 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003140 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003141 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003142 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003143 goto error;
3144 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003146 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003148 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003149
3150error:
3151
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003152 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003154 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003155}
3156
Michal Vasko0d343d12015-08-24 14:57:36 +02003157/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003158static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003159read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003160 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003161{
Radek Krejci76512572015-08-04 09:47:08 +02003162 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003163 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 struct lyxml_elem *sub, *next;
3165 const char *value;
3166 char *endptr;
3167 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003168 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003169 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003173 if (!llist) {
3174 LOGMEM;
3175 return NULL;
3176 }
Radek Krejci76512572015-08-04 09:47:08 +02003177 llist->nodetype = LYS_LEAFLIST;
3178 llist->prev = (struct lys_node *)llist;
3179 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003180
Michal Vaskoe0c59842015-09-24 13:52:20 +02003181 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3182 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 goto error;
3184 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003185
Radek Krejcia9544502015-08-14 08:24:29 +02003186 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003187
Radek Krejcic4283442016-04-22 09:19:27 +02003188 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003189 goto error;
3190 }
3191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003193 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3194 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003195 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003196 continue;
3197 }
3198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003199 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003200 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003201 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 goto error;
3203 }
Michal Vasko88c29542015-11-27 14:57:53 +01003204 /* HACK for unres */
3205 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003206 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci08a11052016-06-13 15:14:30 +02003207 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003208 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003209 goto error;
3210 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003211 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 } else if (!strcmp(sub->name, "units")) {
3213 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003214 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 goto error;
3216 }
3217 GETVAL(value, sub, "name");
3218 llist->units = lydict_insert(module->ctx, value, strlen(value));
3219 } else if (!strcmp(sub->name, "ordered-by")) {
3220 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003221 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 goto error;
3223 }
3224 /* just checking the flags in llist is not sufficient, we would
3225 * allow multiple ordered-by statements with the "system" value
3226 */
3227 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003228
Radek Krejci1574a8d2015-08-03 14:16:52 +02003229 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3231 * state data
3232 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003233 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 continue;
3235 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 GETVAL(value, sub, "value");
3238 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003239 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003241 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003242 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003243 } /* else system is the default value, so we can ignore it */
3244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 } else if (!strcmp(sub->name, "must")) {
3246 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003247 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003248 } else if (!strcmp(sub->name, "if-feature")) {
3249 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003252 } else if (!strcmp(sub->name, "min-elements")) {
3253 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003254 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 goto error;
3256 }
3257 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003259 GETVAL(value, sub, "value");
3260 while (isspace(value[0])) {
3261 value++;
3262 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 /* convert it to uint32_t */
3265 errno = 0;
3266 endptr = NULL;
3267 val = strtoul(value, &endptr, 10);
3268 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003269 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 goto error;
3271 }
3272 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003273 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003274 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3275 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003276 goto error;
3277 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 } else if (!strcmp(sub->name, "max-elements")) {
3279 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003280 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 goto error;
3282 }
3283 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 GETVAL(value, sub, "value");
3286 while (isspace(value[0])) {
3287 value++;
3288 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003289
Radek Krejci0d7b2472016-02-12 11:11:03 +01003290 if (!strcmp(value, "unbounded")) {
3291 llist->max = 0;
3292 } else {
3293 /* convert it to uint32_t */
3294 errno = 0;
3295 endptr = NULL;
3296 val = strtoul(value, &endptr, 10);
3297 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003298 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003299 goto error;
3300 }
3301 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003302 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003303 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3304 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003305 goto error;
3306 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003308 } else if (!strcmp(sub->name, "when")) {
3309 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003310 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003311 goto error;
3312 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003313
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003314 llist->when = read_yin_when(module, sub);
3315 if (!llist->when) {
3316 goto error;
3317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003319 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003322
Michal Vasko88c29542015-11-27 14:57:53 +01003323 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003327 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003328 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 goto error;
3330 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 /* middle part - process nodes with cardinality of 0..n */
3333 if (c_must) {
3334 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003335 if (!llist->must) {
3336 LOGMEM;
3337 goto error;
3338 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003340 if (c_ftrs) {
3341 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003342 if (!llist->features) {
3343 LOGMEM;
3344 goto error;
3345 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003346 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003347
Radek Krejci73adb602015-07-02 18:07:40 +02003348 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003350 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3351 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 if (r) {
3353 goto error;
3354 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003355 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003356 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003357 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003358 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003359 goto error;
3360 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003365
3366error:
3367
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003368 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003370 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003371}
3372
Michal Vasko0d343d12015-08-24 14:57:36 +02003373/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003374static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003375read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3376 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003377{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003378 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003379 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003381 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003382 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003384 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 char *auxs;
3386 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 /* init */
3389 memset(&root, 0, sizeof root);
3390 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003392 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003393 if (!list) {
3394 LOGMEM;
3395 return NULL;
3396 }
Radek Krejci76512572015-08-04 09:47:08 +02003397 list->nodetype = LYS_LIST;
3398 list->prev = (struct lys_node *)list;
3399 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003400
Michal Vaskoe0c59842015-09-24 13:52:20 +02003401 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3402 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 goto error;
3404 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003405
Radek Krejcia9544502015-08-14 08:24:29 +02003406 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 /* process list's specific children */
3409 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003410 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3411 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003412 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003413 continue;
3414 }
3415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 /* data statements */
3417 if (!strcmp(sub->name, "container") ||
3418 !strcmp(sub->name, "leaf-list") ||
3419 !strcmp(sub->name, "leaf") ||
3420 !strcmp(sub->name, "list") ||
3421 !strcmp(sub->name, "choice") ||
3422 !strcmp(sub->name, "uses") ||
3423 !strcmp(sub->name, "grouping") ||
3424 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003425 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003426 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 /* array counters */
3429 } else if (!strcmp(sub->name, "key")) {
3430 /* check cardinality 0..1 */
3431 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003432 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 goto error;
3434 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 /* count the number of keys */
3437 GETVAL(value, sub, "value");
3438 key_str = value;
3439 while ((value = strpbrk(value, " \t\n"))) {
3440 list->keys_size++;
3441 while (isspace(*value)) {
3442 value++;
3443 }
3444 }
3445 list->keys_size++;
3446 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003447 if (!list->keys) {
3448 LOGMEM;
3449 goto error;
3450 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 } else if (!strcmp(sub->name, "unique")) {
3452 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003453 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003454 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 } else if (!strcmp(sub->name, "typedef")) {
3456 c_tpdf++;
3457 } else if (!strcmp(sub->name, "must")) {
3458 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003459 } else if (!strcmp(sub->name, "if-feature")) {
3460 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 /* optional stetments */
3463 } else if (!strcmp(sub->name, "ordered-by")) {
3464 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003465 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 goto error;
3467 }
3468 /* just checking the flags in llist is not sufficient, we would
3469 * allow multiple ordered-by statements with the "system" value
3470 */
3471 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003472
Radek Krejci1574a8d2015-08-03 14:16:52 +02003473 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3475 * state data
3476 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003477 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 continue;
3479 }
Radek Krejci345ad742015-06-03 11:04:18 +02003480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 GETVAL(value, sub, "value");
3482 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003483 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003485 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 goto error;
3487 }
3488 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003489 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 } else if (!strcmp(sub->name, "min-elements")) {
3491 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003492 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 goto error;
3494 }
3495 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 GETVAL(value, sub, "value");
3498 while (isspace(value[0])) {
3499 value++;
3500 }
Radek Krejci345ad742015-06-03 11:04:18 +02003501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 /* convert it to uint32_t */
3503 errno = 0;
3504 auxs = NULL;
3505 val = strtoul(value, &auxs, 10);
3506 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003507 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 goto error;
3509 }
3510 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003511 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003512 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3513 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003514 lyxml_free(module->ctx, sub);
3515 goto error;
3516 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003517 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 } else if (!strcmp(sub->name, "max-elements")) {
3519 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003520 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 goto error;
3522 }
3523 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 GETVAL(value, sub, "value");
3526 while (isspace(value[0])) {
3527 value++;
3528 }
Radek Krejci345ad742015-06-03 11:04:18 +02003529
Radek Krejci0d7b2472016-02-12 11:11:03 +01003530 if (!strcmp(value, "unbounded")) {
3531 list->max = 0;;
3532 } else {
3533 /* convert it to uint32_t */
3534 errno = 0;
3535 auxs = NULL;
3536 val = strtoul(value, &auxs, 10);
3537 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003538 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003539 goto error;
3540 }
3541 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003542 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003543 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3544 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003545 goto error;
3546 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003548 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003549 } else if (!strcmp(sub->name, "when")) {
3550 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003551 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003552 goto error;
3553 }
3554
3555 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003556 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003557 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003558 goto error;
3559 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003560 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003561 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003562 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003563 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 }
3565 }
Radek Krejci345ad742015-06-03 11:04:18 +02003566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003568 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003569 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 goto error;
3571 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3574 if (c_tpdf) {
3575 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003576 if (!list->tpdf) {
3577 LOGMEM;
3578 goto error;
3579 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003581 if (c_must) {
3582 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003583 if (!list->must) {
3584 LOGMEM;
3585 goto error;
3586 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003587 }
3588 if (c_ftrs) {
3589 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003590 if (!list->features) {
3591 LOGMEM;
3592 goto error;
3593 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003594 }
Radek Krejci73adb602015-07-02 18:07:40 +02003595 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003597 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3598 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 if (r) {
3600 goto error;
3601 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003602 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003603 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003604 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003605 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003606 goto error;
3607 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003608 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003609 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3610 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003611 if (r) {
3612 goto error;
3613 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 }
3615 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003616
Radek Krejcic4283442016-04-22 09:19:27 +02003617 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003618 goto error;
3619 }
3620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 /* last part - process data nodes */
3622 LY_TREE_FOR_SAFE(root.child, next, sub) {
3623 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003624 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003626 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003628 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003629 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003630 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003632 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003634 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003636 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003638 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003639 } else {
3640 LOGINT;
3641 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003642 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003643 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003644 goto error;
3645 }
Radek Krejci73adb602015-07-02 18:07:40 +02003646
Michal Vasko345da0a2015-12-02 10:35:55 +01003647 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003648 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003649
Radek Krejci461efb92016-02-12 15:52:18 +01003650 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003651 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003652 goto error;
3653 }
3654 } /* 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 +02003655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 /* process unique statements */
3657 if (c_uniq) {
3658 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003659 if (!list->unique) {
3660 LOGMEM;
3661 goto error;
3662 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003663
Radek Krejci461efb92016-02-12 15:52:18 +01003664 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3665 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3666 list->unique_size++;
3667 if (r) {
3668 goto error;
3669 }
3670
3671 lyxml_free(module->ctx, sub);
3672 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003673 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003676
3677error:
3678
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003679 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003681 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 }
3683 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003684 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003688}
3689
Michal Vasko0d343d12015-08-24 14:57:36 +02003690/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003691static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003692read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3693 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003694{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003696 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003697 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003698 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 const char *value;
3700 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003701 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 /* init */
3704 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003707 if (!cont) {
3708 LOGMEM;
3709 return NULL;
3710 }
Radek Krejci76512572015-08-04 09:47:08 +02003711 cont->nodetype = LYS_CONTAINER;
3712 cont->prev = (struct lys_node *)cont;
3713 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003714
Michal Vaskoe0c59842015-09-24 13:52:20 +02003715 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3716 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 goto error;
3718 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003719
Radek Krejcia9544502015-08-14 08:24:29 +02003720 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 /* process container's specific children */
3723 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003724 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003725 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003726 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003727 continue;
3728 }
3729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 if (!strcmp(sub->name, "presence")) {
3731 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003732 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 goto error;
3734 }
3735 GETVAL(value, sub, "value");
3736 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003737
Michal Vasko345da0a2015-12-02 10:35:55 +01003738 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003739 } else if (!strcmp(sub->name, "when")) {
3740 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003741 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003742 goto error;
3743 }
3744
3745 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003746 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003747 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003748 goto error;
3749 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003750 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 /* data statements */
3753 } else if (!strcmp(sub->name, "container") ||
3754 !strcmp(sub->name, "leaf-list") ||
3755 !strcmp(sub->name, "leaf") ||
3756 !strcmp(sub->name, "list") ||
3757 !strcmp(sub->name, "choice") ||
3758 !strcmp(sub->name, "uses") ||
3759 !strcmp(sub->name, "grouping") ||
3760 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003761 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003762 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003764 /* array counters */
3765 } else if (!strcmp(sub->name, "typedef")) {
3766 c_tpdf++;
3767 } else if (!strcmp(sub->name, "must")) {
3768 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003769 } else if (!strcmp(sub->name, "if-feature")) {
3770 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003772 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 }
3775 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3778 if (c_tpdf) {
3779 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003780 if (!cont->tpdf) {
3781 LOGMEM;
3782 goto error;
3783 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 }
3785 if (c_must) {
3786 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003787 if (!cont->must) {
3788 LOGMEM;
3789 goto error;
3790 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003791 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003792 if (c_ftrs) {
3793 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003794 if (!cont->features) {
3795 LOGMEM;
3796 goto error;
3797 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003798 }
Radek Krejci800af702015-06-02 13:46:01 +02003799
Radek Krejci73adb602015-07-02 18:07:40 +02003800 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003802 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3803 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 if (r) {
3805 goto error;
3806 }
3807 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003808 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3809 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 if (r) {
3811 goto error;
3812 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003813 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003814 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003815 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003816 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003817 goto error;
3818 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003821
Radek Krejcic4283442016-04-22 09:19:27 +02003822 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003823 goto error;
3824 }
3825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 /* last part - process data nodes */
3827 LY_TREE_FOR_SAFE(root.child, next, sub) {
3828 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003829 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003831 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003833 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003835 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003837 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003839 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003841 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003842 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003843 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003845 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 goto error;
3847 }
Radek Krejci73adb602015-07-02 18:07:40 +02003848
Michal Vasko345da0a2015-12-02 10:35:55 +01003849 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003853
3854error:
3855
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003856 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003858 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003862}
3863
Michal Vasko0d343d12015-08-24 14:57:36 +02003864/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003865static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003866read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003867 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003868{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003870 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003871 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003872 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 int r;
3874 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 /* init */
3877 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003880 if (!grp) {
3881 LOGMEM;
3882 return NULL;
3883 }
Radek Krejci76512572015-08-04 09:47:08 +02003884 grp->nodetype = LYS_GROUPING;
3885 grp->prev = (struct lys_node *)grp;
3886 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003887
Michal Vasko71e1aa82015-08-12 12:17:51 +02003888 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 goto error;
3890 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891
Radek Krejcia9544502015-08-14 08:24:29 +02003892 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3893
Radek Krejci1d82ef62015-08-07 14:44:40 +02003894 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003895 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3896 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003897 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003898 continue;
3899 }
3900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 /* data statements */
3902 if (!strcmp(sub->name, "container") ||
3903 !strcmp(sub->name, "leaf-list") ||
3904 !strcmp(sub->name, "leaf") ||
3905 !strcmp(sub->name, "list") ||
3906 !strcmp(sub->name, "choice") ||
3907 !strcmp(sub->name, "uses") ||
3908 !strcmp(sub->name, "grouping") ||
3909 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003910 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003911 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 /* array counters */
3914 } else if (!strcmp(sub->name, "typedef")) {
3915 c_tpdf++;
3916 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003917 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 goto error;
3919 }
3920 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3923 if (c_tpdf) {
3924 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003925 if (!grp->tpdf) {
3926 LOGMEM;
3927 goto error;
3928 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003930 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003931 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3932 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003933 if (r) {
3934 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003937
Radek Krejcic4283442016-04-22 09:19:27 +02003938 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003939 goto error;
3940 }
3941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02003943 if (!root.child) {
3944 LOGWRN("Grouping \"%s\" without children.", retval->name);
3945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 LY_TREE_FOR_SAFE(root.child, next, sub) {
3947 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003948 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003950 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003958 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003964 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 goto error;
3966 }
Radek Krejci73adb602015-07-02 18:07:40 +02003967
Michal Vasko345da0a2015-12-02 10:35:55 +01003968 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003972
3973error:
3974
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003975 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003976 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003977 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003978 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003981}
3982
Michal Vasko0d343d12015-08-24 14:57:36 +02003983/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003984static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003985read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3986 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003987{
Radek Krejcie0674f82015-06-15 13:58:51 +02003988 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003989 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003990 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003991 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003992 int r;
3993 int c_tpdf = 0;
3994
Radek Krejcie0674f82015-06-15 13:58:51 +02003995 /* init */
3996 memset(&root, 0, sizeof root);
3997
Michal Vasko38d01f72015-06-15 09:41:06 +02003998 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01003999 if (!inout) {
4000 LOGMEM;
4001 return NULL;
4002 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004003 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004004
4005 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004006 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004007 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004008 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004009 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004010 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004011 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004012 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004013 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004014 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004015 }
4016
Radek Krejci76512572015-08-04 09:47:08 +02004017 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004018
Radek Krejci6a113852015-07-03 16:04:20 +02004019 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004020 goto error;
4021 }
4022
Radek Krejcia9544502015-08-14 08:24:29 +02004023 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4024
Michal Vasko38d01f72015-06-15 09:41:06 +02004025 /* data statements */
4026 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004027 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4028 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004029 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004030 continue;
4031 }
4032
Michal Vasko38d01f72015-06-15 09:41:06 +02004033 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004034 !strcmp(sub->name, "leaf-list") ||
4035 !strcmp(sub->name, "leaf") ||
4036 !strcmp(sub->name, "list") ||
4037 !strcmp(sub->name, "choice") ||
4038 !strcmp(sub->name, "uses") ||
4039 !strcmp(sub->name, "grouping") ||
4040 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004041 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004042 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004044 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004045 } else if (!strcmp(sub->name, "typedef")) {
4046 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004047
Michal Vasko38d01f72015-06-15 09:41:06 +02004048 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004049 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004050 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004051 }
4052 }
4053
4054 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4055 if (c_tpdf) {
4056 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004057 if (!inout->tpdf) {
4058 LOGMEM;
4059 goto error;
4060 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004061 }
4062
Radek Krejci73adb602015-07-02 18:07:40 +02004063 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004064 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4065 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004066 if (r) {
4067 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004068 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004069 }
4070
Radek Krejcic4283442016-04-22 09:19:27 +02004071 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004072 goto error;
4073 }
4074
Michal Vasko38d01f72015-06-15 09:41:06 +02004075 /* last part - process data nodes */
4076 LY_TREE_FOR_SAFE(root.child, next, sub) {
4077 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004078 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004079 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004081 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004083 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004084 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004085 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004086 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004087 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004088 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004089 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004090 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004091 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004092 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004093 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004094 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004095 goto error;
4096 }
Radek Krejci73adb602015-07-02 18:07:40 +02004097
Michal Vasko345da0a2015-12-02 10:35:55 +01004098 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004099 }
4100
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 return retval;
4102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004104
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004105 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004106 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004107 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004108 }
4109
4110 return NULL;
4111}
4112
Michal Vasko0d343d12015-08-24 14:57:36 +02004113/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004114static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004115read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4116 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004117{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004118 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004119 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004120 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004121 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004122 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004123 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004124
Michal Vaskoc6551b32015-06-16 10:51:43 +02004125 memset(&root, 0, sizeof root);
4126
Michal Vasko0ea41032015-06-16 08:53:55 +02004127 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004128 if (!notif) {
4129 LOGMEM;
4130 return NULL;
4131 }
Radek Krejci76512572015-08-04 09:47:08 +02004132 notif->nodetype = LYS_NOTIF;
4133 notif->prev = (struct lys_node *)notif;
4134 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004135
Radek Krejci6a113852015-07-03 16:04:20 +02004136 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004137 goto error;
4138 }
4139
Radek Krejcia9544502015-08-14 08:24:29 +02004140 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4141
Michal Vasko0ea41032015-06-16 08:53:55 +02004142 /* process rpc's specific children */
4143 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004144 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4145 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004146 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004147 continue;
4148 }
4149
Michal Vasko0ea41032015-06-16 08:53:55 +02004150 /* data statements */
4151 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004152 !strcmp(sub->name, "leaf-list") ||
4153 !strcmp(sub->name, "leaf") ||
4154 !strcmp(sub->name, "list") ||
4155 !strcmp(sub->name, "choice") ||
4156 !strcmp(sub->name, "uses") ||
4157 !strcmp(sub->name, "grouping") ||
4158 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004159 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004160 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004162 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004163 } else if (!strcmp(sub->name, "typedef")) {
4164 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004165 } else if (!strcmp(sub->name, "if-feature")) {
4166 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004167 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004168 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004169 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004170 }
4171 }
4172
4173 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4174 if (c_tpdf) {
4175 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004176 if (!notif->tpdf) {
4177 LOGMEM;
4178 goto error;
4179 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004180 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004181 if (c_ftrs) {
4182 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004183 if (!notif->features) {
4184 LOGMEM;
4185 goto error;
4186 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004187 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004188
Radek Krejci73adb602015-07-02 18:07:40 +02004189 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004190 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004191 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4192 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004193 if (r) {
4194 goto error;
4195 }
Radek Krejci96299152016-06-22 10:17:50 +02004196 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004197 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004198 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004199 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004200 goto error;
4201 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004202 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004203 }
4204
Radek Krejcic4283442016-04-22 09:19:27 +02004205 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004206 goto error;
4207 }
4208
Michal Vasko0ea41032015-06-16 08:53:55 +02004209 /* last part - process data nodes */
4210 LY_TREE_FOR_SAFE(root.child, next, sub) {
4211 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004212 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004213 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004215 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004216 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004217 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004218 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004219 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004220 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004221 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004222 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004223 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004224 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004225 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004226 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004227 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004228 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004229 goto error;
4230 }
Radek Krejci73adb602015-07-02 18:07:40 +02004231
Michal Vasko345da0a2015-12-02 10:35:55 +01004232 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004233 }
4234
Michal Vasko0ea41032015-06-16 08:53:55 +02004235 return retval;
4236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004238
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004239 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004240 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004241 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 }
4243
4244 return NULL;
4245}
4246
Michal Vasko0d343d12015-08-24 14:57:36 +02004247/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004248static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004249read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4250 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004251{
Radek Krejcie0674f82015-06-15 13:58:51 +02004252 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004253 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004254 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004255 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004256 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004257 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004258
Radek Krejcie0674f82015-06-15 13:58:51 +02004259 /* init */
4260 memset(&root, 0, sizeof root);
4261
Michal Vasko38d01f72015-06-15 09:41:06 +02004262 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004263 if (!rpc) {
4264 LOGMEM;
4265 return NULL;
4266 }
Radek Krejci76512572015-08-04 09:47:08 +02004267 rpc->nodetype = LYS_RPC;
4268 rpc->prev = (struct lys_node *)rpc;
4269 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004270
Radek Krejci6a113852015-07-03 16:04:20 +02004271 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004272 goto error;
4273 }
4274
Radek Krejcia9544502015-08-14 08:24:29 +02004275 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4276
Michal Vasko38d01f72015-06-15 09:41:06 +02004277 /* process rpc's specific children */
4278 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004279 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4280 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004281 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004282 continue;
4283 }
4284
Michal Vasko38d01f72015-06-15 09:41:06 +02004285 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004287 && (rpc->child->nodetype == LYS_INPUT
4288 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004289 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004290 goto error;
4291 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004292 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004293 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004294 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004296 && (rpc->child->nodetype == LYS_INPUT
4297 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004298 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004299 goto error;
4300 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004301 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004302 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004304 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004305 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004306 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004307 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004309 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004310 } else if (!strcmp(sub->name, "typedef")) {
4311 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004312 } else if (!strcmp(sub->name, "if-feature")) {
4313 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004314 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004315 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004316 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004317 }
4318 }
4319
4320 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4321 if (c_tpdf) {
4322 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004323 if (!rpc->tpdf) {
4324 LOGMEM;
4325 goto error;
4326 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004327 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004328 if (c_ftrs) {
4329 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004330 if (!rpc->features) {
4331 LOGMEM;
4332 goto error;
4333 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004334 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004335
Radek Krejci73adb602015-07-02 18:07:40 +02004336 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004337 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004338 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4339 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004340 if (r) {
4341 goto error;
4342 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004343 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004344 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004345 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004346 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004347 goto error;
4348 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004349 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004350 }
4351
Radek Krejcic4283442016-04-22 09:19:27 +02004352 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004353 goto error;
4354 }
4355
Michal Vasko38d01f72015-06-15 09:41:06 +02004356 /* last part - process data nodes */
4357 LY_TREE_FOR_SAFE(root.child, next, sub) {
4358 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004359 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004360 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004361 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004362 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004363 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004364 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004365 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004366 goto error;
4367 }
Radek Krejci73adb602015-07-02 18:07:40 +02004368
Michal Vasko345da0a2015-12-02 10:35:55 +01004369 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004370 }
4371
Michal Vasko38d01f72015-06-15 09:41:06 +02004372 return retval;
4373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004375
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004376 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004377 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004378 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004379 }
4380
4381 return NULL;
4382}
4383
Michal Vasko0d343d12015-08-24 14:57:36 +02004384/* logs directly
4385 *
Radek Krejci74705112015-06-05 10:25:44 +02004386 * resolve - referenced grouping should be bounded to the namespace (resolved)
4387 * only when uses does not appear in grouping. In a case of grouping's uses,
4388 * we just get information but we do not apply augment or refine to it.
4389 */
Radek Krejci76512572015-08-04 09:47:08 +02004390static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02004391read_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 +02004392{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004393 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004394 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004395 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004397 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004398 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004401 if (!uses) {
4402 LOGMEM;
4403 return NULL;
4404 }
Radek Krejci76512572015-08-04 09:47:08 +02004405 uses->nodetype = LYS_USES;
4406 uses->prev = (struct lys_node *)uses;
4407 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004408
Radek Krejcia9544502015-08-14 08:24:29 +02004409 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004411
Michal Vaskoe0c59842015-09-24 13:52:20 +02004412 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02004413 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004414 goto error;
4415 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004416
Radek Krejcia9544502015-08-14 08:24:29 +02004417 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004420 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004421 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4422 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004423 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004424 continue;
4425 }
4426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 if (!strcmp(sub->name, "refine")) {
4428 c_ref++;
4429 } else if (!strcmp(sub->name, "augment")) {
4430 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004431 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004432 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004433 } else if (!strcmp(sub->name, "when")) {
4434 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004435 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004436 goto error;
4437 }
4438
4439 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004440 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004441 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004442 goto error;
4443 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004444 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004446 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 }
4449 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004451 /* process properties with cardinality 0..n */
4452 if (c_ref) {
4453 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004454 if (!uses->refine) {
4455 LOGMEM;
4456 goto error;
4457 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004458 }
4459 if (c_aug) {
4460 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004461 if (!uses->augment) {
4462 LOGMEM;
4463 goto error;
4464 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004466 if (c_ftrs) {
4467 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004468 if (!uses->features) {
4469 LOGMEM;
4470 goto error;
4471 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004472 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004473
Radek Krejcic4283442016-04-22 09:19:27 +02004474 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004475 goto error;
4476 }
4477
Radek Krejcia9544502015-08-14 08:24:29 +02004478 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004480 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4481 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004482 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004483 goto error;
4484 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004485 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004486 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4487 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004488 if (r) {
4489 goto error;
4490 }
4491 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004492 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004493 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004494 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004495 goto error;
4496 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 }
4498 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004499
Radek Krejci48464ed2016-03-17 15:44:09 +01004500 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004501 goto error;
4502 }
Radek Krejci74705112015-06-05 10:25:44 +02004503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004505
4506error:
4507
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004508 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004511}
4512
Michal Vasko0d343d12015-08-24 14:57:36 +02004513/* logs directly
4514 *
4515 * common code for yin_read_module() and yin_read_submodule()
4516 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517static int
Radek Krejcic071c542016-01-27 14:57:51 +01004518read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4519 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004520{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004522 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004523 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004524 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004525 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004527 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02004528 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01004529 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004530 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004531 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 +02004532
Radek Krejcic071c542016-01-27 14:57:51 +01004533 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004534 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 /* init */
4537 memset(&root, 0, sizeof root);
4538 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004539 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004541 /*
4542 * in the first run, we process elements with cardinality of 1 or 0..1 and
4543 * count elements with cardinality 0..n. Data elements (choices, containers,
4544 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4545 * need have all top-level and groupings already prepared at that time. In
4546 * the middle loop, we process other elements with carinality of 0..n since
4547 * we need to allocate arrays to store them.
4548 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004549 LY_TREE_FOR_SAFE(yin->child, next, child) {
4550 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004551 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004552 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004553 continue;
4554 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004555
Radek Krejcic071c542016-01-27 14:57:51 +01004556 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004557 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004558 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004559 goto error;
4560 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004561 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004562 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004563 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004564 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004565 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004566 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 goto error;
4568 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004569 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004570 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 goto error;
4572 }
4573 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004574 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004575 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4576 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004577 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 goto error;
4579 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004580 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004581 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004582 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004583 goto error;
4584 }
Radek Krejcif3886932015-06-04 17:36:06 +02004585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004587 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004588 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004590 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004591 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004593 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004594 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004595 goto error;
4596 }
4597 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004598 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 /* check here differs from a generic prefix check, since this prefix
4600 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004601 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004602 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004603 goto error;
4604 }
Radek Krejcic071c542016-01-27 14:57:51 +01004605 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004608 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004609
4610 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004611 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004613 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004615 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004616 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004617 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004620 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004621 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004622 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004623 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004624 lyxml_unlink_elem(ctx, child, 2);
4625 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004626
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004628 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004630 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 } else if (!strcmp(child->name, "container") ||
4634 !strcmp(child->name, "leaf-list") ||
4635 !strcmp(child->name, "leaf") ||
4636 !strcmp(child->name, "list") ||
4637 !strcmp(child->name, "choice") ||
4638 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004639 !strcmp(child->name, "anyxml") ||
4640 !strcmp(child->name, "rpc") ||
4641 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004642 lyxml_unlink_elem(ctx, child, 2);
4643 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004644
Radek Krejci1d82ef62015-08-07 14:44:40 +02004645 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004647 lyxml_unlink_elem(ctx, child, 2);
4648 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004652 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004653 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 goto error;
4655 }
Radek Krejcic071c542016-01-27 14:57:51 +01004656 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004657 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004658 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 goto error;
4660 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004661 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004662 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004663 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664 goto error;
4665 }
Radek Krejcic071c542016-01-27 14:57:51 +01004666 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004667 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004668 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 goto error;
4670 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004672 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004673 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 goto error;
4675 }
Radek Krejcic071c542016-01-27 14:57:51 +01004676 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004677 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004678 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 goto error;
4680 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004681 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004682 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004683 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 goto error;
4685 }
Radek Krejcic071c542016-01-27 14:57:51 +01004686 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004687 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004688 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 goto error;
4690 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004691 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004693 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004694 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 goto error;
4696 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004697 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 if (strcmp(value, "1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004699 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 goto error;
4701 }
Radek Krejcic071c542016-01-27 14:57:51 +01004702 version_flag = 1;
4703 if (!submodule) {
4704 module->version = 1;
4705 } /* TODO else check for the submodule's same version as in main module, waits for YANG 1.1 support */
Michal Vasko345da0a2015-12-02 10:35:55 +01004706 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004707
Radek Krejci1d82ef62015-08-07 14:44:40 +02004708 } else if (!strcmp(child->name, "extension")) {
4709 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004710
Radek Krejci3d468122015-10-02 13:36:12 +02004711 /* we have the following supported (hardcoded) extensions: */
4712 /* ietf-netconf's get-filter-element-attributes */
4713 if (!strcmp(module->ns, LY_NSNC) &&
4714 !strcmp(value, "get-filter-element-attributes")) {
4715 LOGDBG("NETCONF filter extension found");
4716 /* NACM's default-deny-write and default-deny-all */
4717 } else if (!strcmp(module->ns, LY_NSNACM) &&
4718 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4719 LOGDBG("NACM extension found");
4720 /* other extensions are not supported, so inform about such an extension */
4721 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004722 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004723 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004724 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004725 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004726 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 }
4729 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004730
Radek Krejcic071c542016-01-27 14:57:51 +01004731 /* check for mandatory statements */
4732 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004733 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004734 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004735 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004737 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 goto error;
4739 }
4740 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004741 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 goto error;
4743 }
4744 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 /* allocate arrays for elements with cardinality of 0..n */
4747 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004748 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
4749 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004750 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004751 LOGMEM;
4752 goto error;
4753 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004754 /* set stop block for possible realloc */
4755 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 }
4757 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004758 trg->rev = calloc(c_rev, sizeof *trg->rev);
4759 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004760 LOGMEM;
4761 goto error;
4762 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004763 }
4764 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004765 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4766 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004767 LOGMEM;
4768 goto error;
4769 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 }
4771 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004772 trg->ident = calloc(c_ident, sizeof *trg->ident);
4773 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004774 LOGMEM;
4775 goto error;
4776 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 }
4778 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004779 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
4780 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004781 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004782 LOGMEM;
4783 goto error;
4784 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004785 /* set stop block for possible realloc */
4786 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004788 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004789 trg->augment = calloc(c_aug, sizeof *trg->augment);
4790 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004791 LOGMEM;
4792 goto error;
4793 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004794 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004795 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004796 trg->features = calloc(c_ftrs, sizeof *trg->features);
4797 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004798 LOGMEM;
4799 goto error;
4800 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004801 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004802 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004803 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4804 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004805 LOGMEM;
4806 goto error;
4807 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004809
Michal Vasko2f7925f2015-10-21 15:06:56 +02004810 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4811 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004812 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004813 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4814 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 if (r) {
4816 goto error;
4817 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004818
Radek Krejci1d82ef62015-08-07 14:44:40 +02004819 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004820 memset(&inc, 0, sizeof inc);
4821 /* 1) pass module, not trg, since we want to pass the main module
4822 * 2) we cannot pass directly the structure in the array since
4823 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004824 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004825 if (!r) {
4826 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02004827 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
4828 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004829 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 goto error;
4831 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004832
Radek Krejci1d82ef62015-08-07 14:44:40 +02004833 } else if (!strcmp(child->name, "revision")) {
4834 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004835 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 goto error;
4837 }
Radek Krejcic071c542016-01-27 14:57:51 +01004838 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004839 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004840 for (i = 0; i < trg->rev_size; i++) {
4841 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004842 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4843 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 }
4845 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004846
Radek Krejci1d82ef62015-08-07 14:44:40 +02004847 LY_TREE_FOR(child->child, child2) {
4848 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004849 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004850 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 goto error;
4852 }
Radek Krejcic071c542016-01-27 14:57:51 +01004853 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4854 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004855 goto error;
4856 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004857 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004858 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004859 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 goto error;
4861 }
Radek Krejcic071c542016-01-27 14:57:51 +01004862 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4863 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004864 goto error;
4865 }
4866 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004867 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 goto error;
4869 }
4870 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004873 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004875 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004876 if (!value) {
4877 LOGMEM;
4878 goto error;
4879 }
Radek Krejcic071c542016-01-27 14:57:51 +01004880 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4881 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004883
Radek Krejci749190d2016-02-18 16:26:25 +01004884 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004885 value = trg->rev[0].dsc;
4886 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4887 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004889
Radek Krejci749190d2016-02-18 16:26:25 +01004890 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004891 value = trg->rev[0].ref;
4892 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4893 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 }
4895 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004896
Radek Krejcic071c542016-01-27 14:57:51 +01004897 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004898
Radek Krejci1d82ef62015-08-07 14:44:40 +02004899 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004900 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4901 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 if (r) {
4903 goto error;
4904 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004905
Radek Krejci1d82ef62015-08-07 14:44:40 +02004906 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004907 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4908 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 if (r) {
4910 goto error;
4911 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004912
Radek Krejci1d82ef62015-08-07 14:44:40 +02004913 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004914 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4915 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004916 if (r) {
4917 goto error;
4918 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004919
Radek Krejci1d82ef62015-08-07 14:44:40 +02004920 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004921 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4922 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004923 if (r) {
4924 goto error;
4925 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004926 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4927 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004930 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004931
Radek Krejcib8f98c12016-06-24 10:30:46 +02004932 if (!submodule) {
4933 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02004934 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02004935 if (module->inc_size) {
4936 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
4937 if (!module->inc) {
4938 LOGMEM;
4939 goto error;
4940 }
4941 }
4942 if (module->imp_size) {
4943 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
4944 if (!module->imp) {
4945 LOGMEM;
4946 goto error;
4947 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004948 }
4949 }
Radek Krejcic071c542016-01-27 14:57:51 +01004950
Radek Krejcif5be10f2015-06-16 13:29:36 +02004951 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004952 * refer to them. Submodule's data nodes are stored in the
4953 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004954 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004955 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004956 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004957 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004958 goto error;
4959 }
Radek Krejci74705112015-06-05 10:25:44 +02004960
Michal Vasko345da0a2015-12-02 10:35:55 +01004961 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004962 }
Radek Krejci74705112015-06-05 10:25:44 +02004963
Radek Krejcif5be10f2015-06-16 13:29:36 +02004964 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004965 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004966
Radek Krejci1d82ef62015-08-07 14:44:40 +02004967 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004968 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004969 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004970 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004971 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004972 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004973 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004974 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004975 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004976 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004977 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004978 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004979 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004980 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004981 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004982 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004983 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004984 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004986 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 goto error;
4988 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004989
Michal Vasko345da0a2015-12-02 10:35:55 +01004990 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004992
Michal Vasko2f7925f2015-10-21 15:06:56 +02004993 /* ... and finally augments (last, so we can augment our data, for instance) */
4994 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004995 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
4996 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004997
Michal Vasko2f7925f2015-10-21 15:06:56 +02004998 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004999 goto error;
5000 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005001 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005002 }
5003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005005
5006error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 /* cleanup */
5008 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005009 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 }
5011 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005012 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005014 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005015 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005016 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005019}
5020
Michal Vasko0d343d12015-08-24 14:57:36 +02005021/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005022struct lys_submodule *
5023yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005024{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005025 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005026 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005028
Michal Vasko5a721fd2016-02-16 12:16:48 +01005029 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005030
Radek Krejci722b0072016-02-01 17:09:45 +01005031 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005033 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005034 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005036 /* check root element */
5037 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005038 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 goto error;
5040 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005042 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005043 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 goto error;
5045 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005046
Michal Vasko5a721fd2016-02-16 12:16:48 +01005047 submodule = calloc(1, sizeof *submodule);
5048 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 LOGMEM;
5050 goto error;
5051 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005052
Michal Vasko5a721fd2016-02-16 12:16:48 +01005053 submodule->ctx = module->ctx;
5054 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5055 submodule->type = 1;
5056 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005057
Michal Vasko5a721fd2016-02-16 12:16:48 +01005058 LOGVRB("Reading submodule \"%s\".", submodule->name);
5059 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005060 goto error;
5061 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005063 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005064 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005065
Michal Vasko5a721fd2016-02-16 12:16:48 +01005066 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005067 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005068
5069error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005070 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005071 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005072 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005073
Michal Vasko5a721fd2016-02-16 12:16:48 +01005074 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005075 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005076 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005077 }
5078
Michal Vasko5a721fd2016-02-16 12:16:48 +01005079 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005080
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005081 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5082 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005083 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005084 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005085}
5086
Michal Vasko0d343d12015-08-24 14:57:36 +02005087/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005088struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005089yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005090{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005091 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005092 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005093 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005094 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005095 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005096
Radek Krejcic071c542016-01-27 14:57:51 +01005097 unres = calloc(1, sizeof *unres);
5098 if (!unres) {
5099 LOGMEM;
5100 return NULL;
5101 }
5102
Radek Krejci722b0072016-02-01 17:09:45 +01005103 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005104 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005105 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005108 /* check root element */
5109 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005110 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005111 goto error;
5112 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005115 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 goto error;
5117 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005119 module = calloc(1, sizeof *module);
5120 if (!module) {
5121 LOGMEM;
5122 goto error;
5123 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005125 module->ctx = ctx;
5126 module->name = lydict_insert(ctx, value, strlen(value));
5127 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005128 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005129
Michal Vasko9f258e42016-02-11 11:36:27 +01005130 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005131 if (read_sub_module(module, NULL, yin, unres)) {
5132 goto error;
5133 }
5134
5135 /* resolve rest of unres items */
5136 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 goto error;
5138 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005139
Radek Krejciff4874d2016-03-07 12:30:50 +01005140 if (revision) {
5141 /* check revision of the parsed model */
5142 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005143 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5144 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005145 goto error;
5146 }
5147 }
5148
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005149 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005150 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005152
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005153 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005154 if (!module->implemented) {
5155 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5156 }
Michal Vasko26055752016-05-03 11:36:31 +02005157 if (lys_module_set_implement(module)) {
5158 goto error;
5159 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005160
Michal Vasko26055752016-05-03 11:36:31 +02005161 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5162 goto error;
5163 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005164 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005165 if (!module->inc[i].submodule) {
5166 continue;
5167 }
Michal Vasko26055752016-05-03 11:36:31 +02005168 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5169 goto error;
5170 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005171 }
5172 }
5173
Michal Vasko345da0a2015-12-02 10:35:55 +01005174 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005175 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005176 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005178
5179error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005180 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005181 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005182 unres_schema_free(module, &unres);
5183
5184 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005185 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005186 return NULL;
5187 }
5188
5189 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005190
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005191 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005192 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005194}