blob: 0a29e46a9e53f97571f6267b59176bccbce24092 [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 Krejcic189a952016-07-11 15:27:07 +02002892 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002893 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002894 goto error;
2895 }
2896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002898 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2899 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002900 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002901 continue;
2902 }
2903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002904 if (!strcmp(sub->name, "mandatory")) {
2905 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002906 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907 goto error;
2908 }
2909 /* just checking the flags in leaf is not sufficient, we would allow
2910 * multiple mandatory statements with the "false" value
2911 */
2912 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 GETVAL(value, sub, "value");
2915 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002916 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002917 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002918 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002919 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002920 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 goto error;
2922 }
2923 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002924 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002925 } else if (!strcmp(sub->name, "when")) {
2926 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002927 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002928 goto error;
2929 }
2930
2931 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002932 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002933 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002934 goto error;
2935 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002936 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 } else if (!strcmp(sub->name, "must")) {
2938 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002939 } else if (!strcmp(sub->name, "if-feature")) {
2940 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002943 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002945 }
2946 }
Radek Krejci863c2852015-06-03 15:47:11 +02002947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002948 /* middle part - process nodes with cardinality of 0..n */
2949 if (c_must) {
2950 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002951 if (!anyxml->must) {
2952 LOGMEM;
2953 goto error;
2954 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002956 if (c_ftrs) {
2957 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002958 if (!anyxml->features) {
2959 LOGMEM;
2960 goto error;
2961 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002962 }
Radek Krejci863c2852015-06-03 15:47:11 +02002963
Radek Krejci73adb602015-07-02 18:07:40 +02002964 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002965 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002966 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2967 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002968 if (r) {
2969 goto error;
2970 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002971 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002972 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002973 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002974 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002975 goto error;
2976 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 }
Radek Krejci863c2852015-06-03 15:47:11 +02002979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002981
2982error:
2983
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002984 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02002985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002986 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002987}
2988
Michal Vasko0d343d12015-08-24 14:57:36 +02002989/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002990static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002991read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002992 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002993{
Radek Krejci76512572015-08-04 09:47:08 +02002994 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002995 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 struct lyxml_elem *sub, *next;
2997 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01002998 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002999 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003002 if (!leaf) {
3003 LOGMEM;
3004 return NULL;
3005 }
Radek Krejci76512572015-08-04 09:47:08 +02003006 leaf->nodetype = LYS_LEAF;
3007 leaf->prev = (struct lys_node *)leaf;
3008 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003009
Michal Vaskoe0c59842015-09-24 13:52:20 +02003010 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3011 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003012 goto error;
3013 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003014
Radek Krejcia9544502015-08-14 08:24:29 +02003015 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003016
Radek Krejcic189a952016-07-11 15:27:07 +02003017 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003018 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003019 goto error;
3020 }
3021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003023 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3024 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003025 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003026 continue;
3027 }
3028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003030 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003031 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 goto error;
3033 }
Michal Vasko88c29542015-11-27 14:57:53 +01003034 /* HACK for unres */
3035 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003036 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci08a11052016-06-13 15:14:30 +02003037 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003038 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 goto error;
3040 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003041 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 } else if (!strcmp(sub->name, "default")) {
3043 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003044 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 goto error;
3046 }
3047 GETVAL(value, sub, "value");
3048 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3049 } else if (!strcmp(sub->name, "units")) {
3050 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003051 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 goto error;
3053 }
3054 GETVAL(value, sub, "name");
3055 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3056 } else if (!strcmp(sub->name, "mandatory")) {
3057 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003058 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 goto error;
3060 }
3061 /* just checking the flags in leaf is not sufficient, we would allow
3062 * multiple mandatory statements with the "false" value
3063 */
3064 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 GETVAL(value, sub, "value");
3067 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003068 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003069 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003070 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003071 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003072 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 goto error;
3074 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003075 } else if (!strcmp(sub->name, "when")) {
3076 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003077 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003078 goto error;
3079 }
3080
3081 leaf->when = read_yin_when(module, sub);
3082 if (!leaf->when) {
3083 goto error;
3084 }
3085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003087 c_must++;
3088 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003089 } else if (!strcmp(sub->name, "if-feature")) {
3090 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003094 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003097
Michal Vasko88c29542015-11-27 14:57:53 +01003098 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003102 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003103 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 goto error;
3105 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003106 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003107 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003108 goto error;
3109 }
Radek Krejci841ec082016-04-05 13:05:17 +02003110 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003111 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003112 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003113 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003114 goto error;
3115 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 /* middle part - process nodes with cardinality of 0..n */
3119 if (c_must) {
3120 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003121 if (!leaf->must) {
3122 LOGMEM;
3123 goto error;
3124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003126 if (c_ftrs) {
3127 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003128 if (!leaf->features) {
3129 LOGMEM;
3130 goto error;
3131 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003132 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003133
Radek Krejci73adb602015-07-02 18:07:40 +02003134 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003136 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3137 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003138 if (r) {
3139 goto error;
3140 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003141 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003142 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003143 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003144 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003145 goto error;
3146 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003148 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003150 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003151
3152error:
3153
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003154 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003157}
3158
Michal Vasko0d343d12015-08-24 14:57:36 +02003159/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003160static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003161read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003162 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003163{
Radek Krejci76512572015-08-04 09:47:08 +02003164 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003165 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003166 struct lyxml_elem *sub, *next;
3167 const char *value;
3168 char *endptr;
3169 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003170 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003171 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003174 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003175 if (!llist) {
3176 LOGMEM;
3177 return NULL;
3178 }
Radek Krejci76512572015-08-04 09:47:08 +02003179 llist->nodetype = LYS_LEAFLIST;
3180 llist->prev = (struct lys_node *)llist;
3181 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003182
Michal Vaskoe0c59842015-09-24 13:52:20 +02003183 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3184 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 goto error;
3186 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003187
Radek Krejcia9544502015-08-14 08:24:29 +02003188 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003189
Radek Krejcic189a952016-07-11 15:27:07 +02003190 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003191 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003192 goto error;
3193 }
3194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003196 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3197 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003198 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003199 continue;
3200 }
3201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003203 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003204 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 goto error;
3206 }
Michal Vasko88c29542015-11-27 14:57:53 +01003207 /* HACK for unres */
3208 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003209 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci08a11052016-06-13 15:14:30 +02003210 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003211 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 goto error;
3213 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003214 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 } else if (!strcmp(sub->name, "units")) {
3216 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003217 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 goto error;
3219 }
3220 GETVAL(value, sub, "name");
3221 llist->units = lydict_insert(module->ctx, value, strlen(value));
3222 } else if (!strcmp(sub->name, "ordered-by")) {
3223 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
3227 /* just checking the flags in llist is not sufficient, we would
3228 * allow multiple ordered-by statements with the "system" value
3229 */
3230 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003231
Radek Krejci1574a8d2015-08-03 14:16:52 +02003232 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3234 * state data
3235 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003236 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 continue;
3238 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 GETVAL(value, sub, "value");
3241 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003242 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003244 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003246 } /* else system is the default value, so we can ignore it */
3247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003248 } else if (!strcmp(sub->name, "must")) {
3249 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003250 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003251 } else if (!strcmp(sub->name, "if-feature")) {
3252 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 } else if (!strcmp(sub->name, "min-elements")) {
3256 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003257 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 goto error;
3259 }
3260 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 GETVAL(value, sub, "value");
3263 while (isspace(value[0])) {
3264 value++;
3265 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 /* convert it to uint32_t */
3268 errno = 0;
3269 endptr = NULL;
3270 val = strtoul(value, &endptr, 10);
3271 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003272 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 goto error;
3274 }
3275 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003276 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003277 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3278 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003279 goto error;
3280 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 } else if (!strcmp(sub->name, "max-elements")) {
3282 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003283 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 goto error;
3285 }
3286 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 GETVAL(value, sub, "value");
3289 while (isspace(value[0])) {
3290 value++;
3291 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003292
Radek Krejci0d7b2472016-02-12 11:11:03 +01003293 if (!strcmp(value, "unbounded")) {
3294 llist->max = 0;
3295 } else {
3296 /* convert it to uint32_t */
3297 errno = 0;
3298 endptr = NULL;
3299 val = strtoul(value, &endptr, 10);
3300 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003301 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003302 goto error;
3303 }
3304 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003305 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003306 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3307 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003308 goto error;
3309 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003311 } else if (!strcmp(sub->name, "when")) {
3312 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003313 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003314 goto error;
3315 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003316
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003317 llist->when = read_yin_when(module, sub);
3318 if (!llist->when) {
3319 goto error;
3320 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003322 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003325
Michal Vasko88c29542015-11-27 14:57:53 +01003326 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003330 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003331 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 goto error;
3333 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 /* middle part - process nodes with cardinality of 0..n */
3336 if (c_must) {
3337 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003338 if (!llist->must) {
3339 LOGMEM;
3340 goto error;
3341 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003343 if (c_ftrs) {
3344 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003345 if (!llist->features) {
3346 LOGMEM;
3347 goto error;
3348 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003349 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003350
Radek Krejci73adb602015-07-02 18:07:40 +02003351 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003353 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3354 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 if (r) {
3356 goto error;
3357 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003358 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003359 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003360 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003361 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003362 goto error;
3363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003368
3369error:
3370
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003371 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003374}
3375
Michal Vasko0d343d12015-08-24 14:57:36 +02003376/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003377static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003378read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3379 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003380{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003381 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003382 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003384 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003385 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003387 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 char *auxs;
3389 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 /* init */
3392 memset(&root, 0, sizeof root);
3393 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003396 if (!list) {
3397 LOGMEM;
3398 return NULL;
3399 }
Radek Krejci76512572015-08-04 09:47:08 +02003400 list->nodetype = LYS_LIST;
3401 list->prev = (struct lys_node *)list;
3402 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003403
Michal Vaskoe0c59842015-09-24 13:52:20 +02003404 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3405 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 goto error;
3407 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003408
Radek Krejcia9544502015-08-14 08:24:29 +02003409 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3410
Radek Krejcic189a952016-07-11 15:27:07 +02003411 /* insert the node into the schema tree */
3412 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3413 goto error;
3414 }
3415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 /* process list's specific children */
3417 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003418 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3419 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003420 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003421 continue;
3422 }
3423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003424 /* data statements */
3425 if (!strcmp(sub->name, "container") ||
3426 !strcmp(sub->name, "leaf-list") ||
3427 !strcmp(sub->name, "leaf") ||
3428 !strcmp(sub->name, "list") ||
3429 !strcmp(sub->name, "choice") ||
3430 !strcmp(sub->name, "uses") ||
3431 !strcmp(sub->name, "grouping") ||
3432 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003433 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003434 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 /* array counters */
3437 } else if (!strcmp(sub->name, "key")) {
3438 /* check cardinality 0..1 */
3439 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003440 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 goto error;
3442 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 /* count the number of keys */
3445 GETVAL(value, sub, "value");
3446 key_str = value;
3447 while ((value = strpbrk(value, " \t\n"))) {
3448 list->keys_size++;
3449 while (isspace(*value)) {
3450 value++;
3451 }
3452 }
3453 list->keys_size++;
3454 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003455 if (!list->keys) {
3456 LOGMEM;
3457 goto error;
3458 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 } else if (!strcmp(sub->name, "unique")) {
3460 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003461 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003462 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 } else if (!strcmp(sub->name, "typedef")) {
3464 c_tpdf++;
3465 } else if (!strcmp(sub->name, "must")) {
3466 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003467 } else if (!strcmp(sub->name, "if-feature")) {
3468 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003470 /* optional stetments */
3471 } else if (!strcmp(sub->name, "ordered-by")) {
3472 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003473 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 goto error;
3475 }
3476 /* just checking the flags in llist is not sufficient, we would
3477 * allow multiple ordered-by statements with the "system" value
3478 */
3479 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003480
Radek Krejci1574a8d2015-08-03 14:16:52 +02003481 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3483 * state data
3484 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003485 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 continue;
3487 }
Radek Krejci345ad742015-06-03 11:04:18 +02003488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 GETVAL(value, sub, "value");
3490 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003491 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003493 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 goto error;
3495 }
3496 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003497 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 } else if (!strcmp(sub->name, "min-elements")) {
3499 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003500 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 goto error;
3502 }
3503 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 GETVAL(value, sub, "value");
3506 while (isspace(value[0])) {
3507 value++;
3508 }
Radek Krejci345ad742015-06-03 11:04:18 +02003509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 /* convert it to uint32_t */
3511 errno = 0;
3512 auxs = NULL;
3513 val = strtoul(value, &auxs, 10);
3514 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003515 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003516 goto error;
3517 }
3518 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003519 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003520 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3521 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003522 lyxml_free(module->ctx, sub);
3523 goto error;
3524 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003525 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 } else if (!strcmp(sub->name, "max-elements")) {
3527 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003528 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 goto error;
3530 }
3531 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 GETVAL(value, sub, "value");
3534 while (isspace(value[0])) {
3535 value++;
3536 }
Radek Krejci345ad742015-06-03 11:04:18 +02003537
Radek Krejci0d7b2472016-02-12 11:11:03 +01003538 if (!strcmp(value, "unbounded")) {
3539 list->max = 0;;
3540 } else {
3541 /* convert it to uint32_t */
3542 errno = 0;
3543 auxs = NULL;
3544 val = strtoul(value, &auxs, 10);
3545 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003546 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003547 goto error;
3548 }
3549 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003550 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003551 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3552 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003553 goto error;
3554 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003556 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003557 } else if (!strcmp(sub->name, "when")) {
3558 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003559 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003560 goto error;
3561 }
3562
3563 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003564 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003565 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003566 goto error;
3567 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003568 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003569 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003570 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003571 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 }
3573 }
Radek Krejci345ad742015-06-03 11:04:18 +02003574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003576 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003577 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 goto error;
3579 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3582 if (c_tpdf) {
3583 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003584 if (!list->tpdf) {
3585 LOGMEM;
3586 goto error;
3587 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003589 if (c_must) {
3590 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003591 if (!list->must) {
3592 LOGMEM;
3593 goto error;
3594 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003595 }
3596 if (c_ftrs) {
3597 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003598 if (!list->features) {
3599 LOGMEM;
3600 goto error;
3601 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003602 }
Radek Krejci73adb602015-07-02 18:07:40 +02003603 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003605 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3606 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 if (r) {
3608 goto error;
3609 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003610 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003611 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003612 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003613 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003614 goto error;
3615 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003616 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003617 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3618 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003619 if (r) {
3620 goto error;
3621 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 }
3623 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 /* last part - process data nodes */
3626 LY_TREE_FOR_SAFE(root.child, next, sub) {
3627 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003628 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003629 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003630 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003632 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003634 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003636 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003638 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003640 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003641 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003642 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003643 } else {
3644 LOGINT;
3645 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003646 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003647 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003648 goto error;
3649 }
Radek Krejci73adb602015-07-02 18:07:40 +02003650
Michal Vasko345da0a2015-12-02 10:35:55 +01003651 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003653
Radek Krejci461efb92016-02-12 15:52:18 +01003654 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003655 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003656 goto error;
3657 }
3658 } /* 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 +02003659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 /* process unique statements */
3661 if (c_uniq) {
3662 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003663 if (!list->unique) {
3664 LOGMEM;
3665 goto error;
3666 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003667
Radek Krejci461efb92016-02-12 15:52:18 +01003668 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3669 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3670 list->unique_size++;
3671 if (r) {
3672 goto error;
3673 }
3674
3675 lyxml_free(module->ctx, sub);
3676 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003680
3681error:
3682
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003683 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003684 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003685 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 }
3687 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003688 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003689 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003692}
3693
Michal Vasko0d343d12015-08-24 14:57:36 +02003694/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003695static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003696read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3697 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003698{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003700 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003701 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003702 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 const char *value;
3704 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003705 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 /* init */
3708 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003711 if (!cont) {
3712 LOGMEM;
3713 return NULL;
3714 }
Radek Krejci76512572015-08-04 09:47:08 +02003715 cont->nodetype = LYS_CONTAINER;
3716 cont->prev = (struct lys_node *)cont;
3717 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003718
Michal Vaskoe0c59842015-09-24 13:52:20 +02003719 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3720 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 goto error;
3722 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003723
Radek Krejcia9544502015-08-14 08:24:29 +02003724 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3725
Radek Krejcic189a952016-07-11 15:27:07 +02003726 /* insert the node into the schema tree */
3727 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3728 goto error;
3729 }
3730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 /* process container's specific children */
3732 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003733 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003734 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003735 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003736 continue;
3737 }
3738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 if (!strcmp(sub->name, "presence")) {
3740 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003741 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 goto error;
3743 }
3744 GETVAL(value, sub, "value");
3745 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003746
Michal Vasko345da0a2015-12-02 10:35:55 +01003747 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003748 } else if (!strcmp(sub->name, "when")) {
3749 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003750 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003751 goto error;
3752 }
3753
3754 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003755 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003756 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003757 goto error;
3758 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003759 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 /* data statements */
3762 } else if (!strcmp(sub->name, "container") ||
3763 !strcmp(sub->name, "leaf-list") ||
3764 !strcmp(sub->name, "leaf") ||
3765 !strcmp(sub->name, "list") ||
3766 !strcmp(sub->name, "choice") ||
3767 !strcmp(sub->name, "uses") ||
3768 !strcmp(sub->name, "grouping") ||
3769 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003770 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003771 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 /* array counters */
3774 } else if (!strcmp(sub->name, "typedef")) {
3775 c_tpdf++;
3776 } else if (!strcmp(sub->name, "must")) {
3777 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003778 } else if (!strcmp(sub->name, "if-feature")) {
3779 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003781 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003782 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 }
3784 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3787 if (c_tpdf) {
3788 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003789 if (!cont->tpdf) {
3790 LOGMEM;
3791 goto error;
3792 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 }
3794 if (c_must) {
3795 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003796 if (!cont->must) {
3797 LOGMEM;
3798 goto error;
3799 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003801 if (c_ftrs) {
3802 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003803 if (!cont->features) {
3804 LOGMEM;
3805 goto error;
3806 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003807 }
Radek Krejci800af702015-06-02 13:46:01 +02003808
Radek Krejci73adb602015-07-02 18:07:40 +02003809 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003811 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3812 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 if (r) {
3814 goto error;
3815 }
3816 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003817 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3818 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 if (r) {
3820 goto error;
3821 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003822 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003823 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003824 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003825 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003826 goto error;
3827 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 /* last part - process data nodes */
3832 LY_TREE_FOR_SAFE(root.child, next, sub) {
3833 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003834 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003838 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003842 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003844 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003846 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003848 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003850 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 goto error;
3852 }
Radek Krejci73adb602015-07-02 18:07:40 +02003853
Michal Vasko345da0a2015-12-02 10:35:55 +01003854 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003858
3859error:
3860
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003861 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003863 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003866 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003867}
3868
Michal Vasko0d343d12015-08-24 14:57:36 +02003869/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003870static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003871read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003872 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003873{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003875 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003876 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003877 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 int r;
3879 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003881 /* init */
3882 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003885 if (!grp) {
3886 LOGMEM;
3887 return NULL;
3888 }
Radek Krejci76512572015-08-04 09:47:08 +02003889 grp->nodetype = LYS_GROUPING;
3890 grp->prev = (struct lys_node *)grp;
3891 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003892
Michal Vasko71e1aa82015-08-12 12:17:51 +02003893 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003894 goto error;
3895 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003896
Radek Krejcia9544502015-08-14 08:24:29 +02003897 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3898
Radek Krejcic189a952016-07-11 15:27:07 +02003899 /* insert the node into the schema tree */
3900 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3901 goto error;
3902 }
3903
Radek Krejci1d82ef62015-08-07 14:44:40 +02003904 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003905 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3906 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003907 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003908 continue;
3909 }
3910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 /* data statements */
3912 if (!strcmp(sub->name, "container") ||
3913 !strcmp(sub->name, "leaf-list") ||
3914 !strcmp(sub->name, "leaf") ||
3915 !strcmp(sub->name, "list") ||
3916 !strcmp(sub->name, "choice") ||
3917 !strcmp(sub->name, "uses") ||
3918 !strcmp(sub->name, "grouping") ||
3919 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003920 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003921 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003923 /* array counters */
3924 } else if (!strcmp(sub->name, "typedef")) {
3925 c_tpdf++;
3926 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003927 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 goto error;
3929 }
3930 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3933 if (c_tpdf) {
3934 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003935 if (!grp->tpdf) {
3936 LOGMEM;
3937 goto error;
3938 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003939 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003940 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003941 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3942 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003943 if (r) {
3944 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02003949 if (!root.child) {
3950 LOGWRN("Grouping \"%s\" without children.", retval->name);
3951 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 LY_TREE_FOR_SAFE(root.child, next, sub) {
3953 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003958 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003964 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003966 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003967 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003970 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 goto error;
3972 }
Radek Krejci73adb602015-07-02 18:07:40 +02003973
Michal Vasko345da0a2015-12-02 10:35:55 +01003974 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003978
3979error:
3980
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003981 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003982 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003983 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003984 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003987}
3988
Michal Vasko0d343d12015-08-24 14:57:36 +02003989/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003990static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003991read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3992 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003993{
Radek Krejcie0674f82015-06-15 13:58:51 +02003994 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003995 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003996 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003997 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003998 int r;
3999 int c_tpdf = 0;
4000
Radek Krejcie0674f82015-06-15 13:58:51 +02004001 /* init */
4002 memset(&root, 0, sizeof root);
4003
Michal Vasko38d01f72015-06-15 09:41:06 +02004004 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004005 if (!inout) {
4006 LOGMEM;
4007 return NULL;
4008 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004009 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004010
4011 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004012 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004013 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004014 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004015 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004016 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004017 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004018 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004019 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004020 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004021 }
4022
Radek Krejci76512572015-08-04 09:47:08 +02004023 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004024
Radek Krejci6a113852015-07-03 16:04:20 +02004025 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004026 goto error;
4027 }
4028
Radek Krejcia9544502015-08-14 08:24:29 +02004029 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4030
Radek Krejcic189a952016-07-11 15:27:07 +02004031 /* insert the node into the schema tree */
4032 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4033 goto error;
4034 }
4035
Michal Vasko38d01f72015-06-15 09:41:06 +02004036 /* data statements */
4037 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004038 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4039 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004040 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004041 continue;
4042 }
4043
Michal Vasko38d01f72015-06-15 09:41:06 +02004044 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 !strcmp(sub->name, "leaf-list") ||
4046 !strcmp(sub->name, "leaf") ||
4047 !strcmp(sub->name, "list") ||
4048 !strcmp(sub->name, "choice") ||
4049 !strcmp(sub->name, "uses") ||
4050 !strcmp(sub->name, "grouping") ||
4051 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004052 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004053 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004055 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004056 } else if (!strcmp(sub->name, "typedef")) {
4057 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004058
Michal Vasko38d01f72015-06-15 09:41:06 +02004059 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004060 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004061 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004062 }
4063 }
4064
4065 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4066 if (c_tpdf) {
4067 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004068 if (!inout->tpdf) {
4069 LOGMEM;
4070 goto error;
4071 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004072 }
4073
Radek Krejci73adb602015-07-02 18:07:40 +02004074 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004075 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4076 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004077 if (r) {
4078 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004079 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004080 }
4081
4082 /* last part - process data nodes */
4083 LY_TREE_FOR_SAFE(root.child, next, sub) {
4084 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004086 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004087 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004088 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004089 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004090 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004091 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004092 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004093 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004094 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004095 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004096 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004097 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004098 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004099 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004100 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004101 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004102 goto error;
4103 }
Radek Krejci73adb602015-07-02 18:07:40 +02004104
Michal Vasko345da0a2015-12-02 10:35:55 +01004105 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004106 }
4107
Michal Vasko38d01f72015-06-15 09:41:06 +02004108 return retval;
4109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004110error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004111
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004112 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004113 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004114 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004115 }
4116
4117 return NULL;
4118}
4119
Michal Vasko0d343d12015-08-24 14:57:36 +02004120/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004121static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004122read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4123 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004124{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004125 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004126 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004127 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004128 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004129 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004130 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004131
Michal Vaskoc6551b32015-06-16 10:51:43 +02004132 memset(&root, 0, sizeof root);
4133
Michal Vasko0ea41032015-06-16 08:53:55 +02004134 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004135 if (!notif) {
4136 LOGMEM;
4137 return NULL;
4138 }
Radek Krejci76512572015-08-04 09:47:08 +02004139 notif->nodetype = LYS_NOTIF;
4140 notif->prev = (struct lys_node *)notif;
4141 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004142
Radek Krejci6a113852015-07-03 16:04:20 +02004143 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004144 goto error;
4145 }
4146
Radek Krejcia9544502015-08-14 08:24:29 +02004147 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4148
Radek Krejcic189a952016-07-11 15:27:07 +02004149 /* insert the node into the schema tree */
4150 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4151 goto error;
4152 }
4153
Michal Vasko0ea41032015-06-16 08:53:55 +02004154 /* process rpc's specific children */
4155 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004156 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4157 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004158 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004159 continue;
4160 }
4161
Michal Vasko0ea41032015-06-16 08:53:55 +02004162 /* data statements */
4163 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004164 !strcmp(sub->name, "leaf-list") ||
4165 !strcmp(sub->name, "leaf") ||
4166 !strcmp(sub->name, "list") ||
4167 !strcmp(sub->name, "choice") ||
4168 !strcmp(sub->name, "uses") ||
4169 !strcmp(sub->name, "grouping") ||
4170 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004171 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004172 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004174 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004175 } else if (!strcmp(sub->name, "typedef")) {
4176 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004177 } else if (!strcmp(sub->name, "if-feature")) {
4178 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004179 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004180 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004181 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004182 }
4183 }
4184
4185 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4186 if (c_tpdf) {
4187 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004188 if (!notif->tpdf) {
4189 LOGMEM;
4190 goto error;
4191 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004192 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004193 if (c_ftrs) {
4194 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004195 if (!notif->features) {
4196 LOGMEM;
4197 goto error;
4198 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004199 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004200
Radek Krejci73adb602015-07-02 18:07:40 +02004201 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004202 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004203 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4204 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004205 if (r) {
4206 goto error;
4207 }
Radek Krejci96299152016-06-22 10:17:50 +02004208 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004209 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004210 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004211 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004212 goto error;
4213 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004214 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004215 }
4216
4217 /* last part - process data nodes */
4218 LY_TREE_FOR_SAFE(root.child, next, sub) {
4219 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004220 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004221 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004222 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004223 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004224 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004225 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004226 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004227 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004228 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004229 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004230 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004231 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004232 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004233 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004234 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004235 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004236 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004237 goto error;
4238 }
Radek Krejci73adb602015-07-02 18:07:40 +02004239
Michal Vasko345da0a2015-12-02 10:35:55 +01004240 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004241 }
4242
Michal Vasko0ea41032015-06-16 08:53:55 +02004243 return retval;
4244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004245error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004246
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004247 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004248 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004249 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 }
4251
4252 return NULL;
4253}
4254
Michal Vasko0d343d12015-08-24 14:57:36 +02004255/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004256static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004257read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4258 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004259{
Radek Krejcie0674f82015-06-15 13:58:51 +02004260 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004261 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004262 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004263 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004264 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004265 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004266
Radek Krejcie0674f82015-06-15 13:58:51 +02004267 /* init */
4268 memset(&root, 0, sizeof root);
4269
Michal Vasko38d01f72015-06-15 09:41:06 +02004270 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004271 if (!rpc) {
4272 LOGMEM;
4273 return NULL;
4274 }
Radek Krejci76512572015-08-04 09:47:08 +02004275 rpc->nodetype = LYS_RPC;
4276 rpc->prev = (struct lys_node *)rpc;
4277 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004278
Radek Krejci6a113852015-07-03 16:04:20 +02004279 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004280 goto error;
4281 }
4282
Radek Krejcia9544502015-08-14 08:24:29 +02004283 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4284
Radek Krejcic189a952016-07-11 15:27:07 +02004285 /* insert the node into the schema tree */
4286 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4287 goto error;
4288 }
4289
Michal Vasko38d01f72015-06-15 09:41:06 +02004290 /* process rpc's specific children */
4291 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004292 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4293 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004294 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004295 continue;
4296 }
4297
Michal Vasko38d01f72015-06-15 09:41:06 +02004298 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004300 && (rpc->child->nodetype == LYS_INPUT
4301 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004302 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004303 goto error;
4304 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004305 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004306 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004307 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004309 && (rpc->child->nodetype == LYS_INPUT
4310 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004311 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004312 goto error;
4313 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004314 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004315 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004318 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004319 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004320 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004322 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004323 } else if (!strcmp(sub->name, "typedef")) {
4324 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004325 } else if (!strcmp(sub->name, "if-feature")) {
4326 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004327 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004328 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004329 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004330 }
4331 }
4332
4333 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4334 if (c_tpdf) {
4335 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004336 if (!rpc->tpdf) {
4337 LOGMEM;
4338 goto error;
4339 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004340 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004341 if (c_ftrs) {
4342 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004343 if (!rpc->features) {
4344 LOGMEM;
4345 goto error;
4346 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004347 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004348
Radek Krejci73adb602015-07-02 18:07:40 +02004349 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004350 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004351 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4352 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004353 if (r) {
4354 goto error;
4355 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004356 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004357 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004358 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004359 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004360 goto error;
4361 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004362 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004363 }
4364
4365 /* last part - process data nodes */
4366 LY_TREE_FOR_SAFE(root.child, next, sub) {
4367 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004368 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004369 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004370 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004371 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004372 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004373 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004374 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004375 goto error;
4376 }
Radek Krejci73adb602015-07-02 18:07:40 +02004377
Michal Vasko345da0a2015-12-02 10:35:55 +01004378 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004379 }
4380
Michal Vasko38d01f72015-06-15 09:41:06 +02004381 return retval;
4382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004383error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004384
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004385 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004386 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004387 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004388 }
4389
4390 return NULL;
4391}
4392
Michal Vasko0d343d12015-08-24 14:57:36 +02004393/* logs directly
4394 *
Radek Krejci74705112015-06-05 10:25:44 +02004395 * resolve - referenced grouping should be bounded to the namespace (resolved)
4396 * only when uses does not appear in grouping. In a case of grouping's uses,
4397 * we just get information but we do not apply augment or refine to it.
4398 */
Radek Krejci76512572015-08-04 09:47:08 +02004399static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02004400read_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 +02004401{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004403 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004404 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004406 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004410 if (!uses) {
4411 LOGMEM;
4412 return NULL;
4413 }
Radek Krejci76512572015-08-04 09:47:08 +02004414 uses->nodetype = LYS_USES;
4415 uses->prev = (struct lys_node *)uses;
4416 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004417
Radek Krejcia9544502015-08-14 08:24:29 +02004418 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004420
Michal Vaskoe0c59842015-09-24 13:52:20 +02004421 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02004422 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 goto error;
4424 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004425
Radek Krejcia9544502015-08-14 08:24:29 +02004426 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4427
Radek Krejcic189a952016-07-11 15:27:07 +02004428 /* insert the node into the schema tree */
4429 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4430 goto error;
4431 }
4432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004434 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004435 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4436 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004437 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004438 continue;
4439 }
4440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 if (!strcmp(sub->name, "refine")) {
4442 c_ref++;
4443 } else if (!strcmp(sub->name, "augment")) {
4444 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004445 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004446 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004447 } else if (!strcmp(sub->name, "when")) {
4448 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004449 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004450 goto error;
4451 }
4452
4453 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004454 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004455 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004456 goto error;
4457 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004458 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004460 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004462 }
4463 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 /* process properties with cardinality 0..n */
4466 if (c_ref) {
4467 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004468 if (!uses->refine) {
4469 LOGMEM;
4470 goto error;
4471 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004472 }
4473 if (c_aug) {
4474 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004475 if (!uses->augment) {
4476 LOGMEM;
4477 goto error;
4478 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004480 if (c_ftrs) {
4481 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004482 if (!uses->features) {
4483 LOGMEM;
4484 goto error;
4485 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004486 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004487
Radek Krejcia9544502015-08-14 08:24:29 +02004488 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004490 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4491 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004492 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004493 goto error;
4494 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004495 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004496 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4497 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004498 if (r) {
4499 goto error;
4500 }
4501 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004502 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004503 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004504 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004505 goto error;
4506 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 }
4508 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004509
Radek Krejci48464ed2016-03-17 15:44:09 +01004510 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004511 goto error;
4512 }
Radek Krejci74705112015-06-05 10:25:44 +02004513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004515
4516error:
4517
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004518 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004521}
4522
Michal Vasko0d343d12015-08-24 14:57:36 +02004523/* logs directly
4524 *
4525 * common code for yin_read_module() and yin_read_submodule()
4526 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527static int
Radek Krejcic071c542016-01-27 14:57:51 +01004528read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4529 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004530{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004532 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004533 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004534 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004535 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004537 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02004538 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01004539 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004540 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004541 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 +02004542
Radek Krejcic071c542016-01-27 14:57:51 +01004543 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004544 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 /* init */
4547 memset(&root, 0, sizeof root);
4548 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004549 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004551 /*
4552 * in the first run, we process elements with cardinality of 1 or 0..1 and
4553 * count elements with cardinality 0..n. Data elements (choices, containers,
4554 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4555 * need have all top-level and groupings already prepared at that time. In
4556 * the middle loop, we process other elements with carinality of 0..n since
4557 * we need to allocate arrays to store them.
4558 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004559 LY_TREE_FOR_SAFE(yin->child, next, child) {
4560 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004561 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004562 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 continue;
4564 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004565
Radek Krejcic071c542016-01-27 14:57:51 +01004566 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004568 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 goto error;
4570 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004571 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004573 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004574 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004575 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004576 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 goto error;
4578 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004579 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004580 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 goto error;
4582 }
4583 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004584 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004585 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4586 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004587 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 goto error;
4589 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004590 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004591 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004592 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004593 goto error;
4594 }
Radek Krejcif3886932015-06-04 17:36:06 +02004595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004597 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004598 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004600 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004601 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004603 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004604 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 goto error;
4606 }
4607 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004608 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 /* check here differs from a generic prefix check, since this prefix
4610 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004611 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004612 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 goto error;
4614 }
Radek Krejcic071c542016-01-27 14:57:51 +01004615 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004618 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004619
4620 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004621 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004623 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004625 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004631 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004632 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004633 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004634 lyxml_unlink_elem(ctx, child, 2);
4635 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004636
Radek Krejci1d82ef62015-08-07 14:44:40 +02004637 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004638 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004640 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004643 } else if (!strcmp(child->name, "container") ||
4644 !strcmp(child->name, "leaf-list") ||
4645 !strcmp(child->name, "leaf") ||
4646 !strcmp(child->name, "list") ||
4647 !strcmp(child->name, "choice") ||
4648 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004649 !strcmp(child->name, "anyxml") ||
4650 !strcmp(child->name, "rpc") ||
4651 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004652 lyxml_unlink_elem(ctx, child, 2);
4653 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004654
Radek Krejci1d82ef62015-08-07 14:44:40 +02004655 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004657 lyxml_unlink_elem(ctx, child, 2);
4658 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004660 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004661 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004662 if (trg->dsc) {
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->dsc = 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->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 goto error;
4670 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004672 if (trg->ref) {
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->ref = 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->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 goto error;
4680 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004681 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004682 if (trg->org) {
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->org = 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->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 goto error;
4690 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004691 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004692 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004693 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 goto error;
4695 }
Radek Krejcic071c542016-01-27 14:57:51 +01004696 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004697 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004698 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 goto error;
4700 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004703 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004704 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004705 goto error;
4706 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004707 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 if (strcmp(value, "1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004709 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 goto error;
4711 }
Radek Krejcic071c542016-01-27 14:57:51 +01004712 version_flag = 1;
4713 if (!submodule) {
4714 module->version = 1;
4715 } /* 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 +01004716 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004717
Radek Krejci1d82ef62015-08-07 14:44:40 +02004718 } else if (!strcmp(child->name, "extension")) {
4719 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004720
Radek Krejci3d468122015-10-02 13:36:12 +02004721 /* we have the following supported (hardcoded) extensions: */
4722 /* ietf-netconf's get-filter-element-attributes */
4723 if (!strcmp(module->ns, LY_NSNC) &&
4724 !strcmp(value, "get-filter-element-attributes")) {
4725 LOGDBG("NETCONF filter extension found");
4726 /* NACM's default-deny-write and default-deny-all */
4727 } else if (!strcmp(module->ns, LY_NSNACM) &&
4728 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4729 LOGDBG("NACM extension found");
4730 /* other extensions are not supported, so inform about such an extension */
4731 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004732 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004733 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004734 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004736 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 }
4739 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004740
Radek Krejcic071c542016-01-27 14:57:51 +01004741 /* check for mandatory statements */
4742 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004743 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004744 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004745 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004747 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 goto error;
4749 }
4750 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004751 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 goto error;
4753 }
4754 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 /* allocate arrays for elements with cardinality of 0..n */
4757 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004758 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
4759 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004760 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004761 LOGMEM;
4762 goto error;
4763 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004764 /* set stop block for possible realloc */
4765 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 }
4767 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004768 trg->rev = calloc(c_rev, sizeof *trg->rev);
4769 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004770 LOGMEM;
4771 goto error;
4772 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004773 }
4774 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004775 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4776 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004777 LOGMEM;
4778 goto error;
4779 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 }
4781 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004782 trg->ident = calloc(c_ident, sizeof *trg->ident);
4783 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004784 LOGMEM;
4785 goto error;
4786 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 }
4788 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004789 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
4790 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004791 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004792 LOGMEM;
4793 goto error;
4794 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004795 /* set stop block for possible realloc */
4796 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004798 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004799 trg->augment = calloc(c_aug, sizeof *trg->augment);
4800 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004801 LOGMEM;
4802 goto error;
4803 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004804 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004805 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004806 trg->features = calloc(c_ftrs, sizeof *trg->features);
4807 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004808 LOGMEM;
4809 goto error;
4810 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004811 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004812 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004813 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4814 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004815 LOGMEM;
4816 goto error;
4817 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004818 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004819
Michal Vasko2f7925f2015-10-21 15:06:56 +02004820 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4821 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004822 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004823 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4824 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004825 if (r) {
4826 goto error;
4827 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004828
Radek Krejci1d82ef62015-08-07 14:44:40 +02004829 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004830 memset(&inc, 0, sizeof inc);
4831 /* 1) pass module, not trg, since we want to pass the main module
4832 * 2) we cannot pass directly the structure in the array since
4833 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004834 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004835 if (!r) {
4836 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02004837 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
4838 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004839 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004840 goto error;
4841 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004842
Radek Krejci1d82ef62015-08-07 14:44:40 +02004843 } else if (!strcmp(child->name, "revision")) {
4844 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004845 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004846 goto error;
4847 }
Radek Krejcic071c542016-01-27 14:57:51 +01004848 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004850 for (i = 0; i < trg->rev_size; i++) {
4851 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004852 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4853 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 }
4855 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004856
Radek Krejci1d82ef62015-08-07 14:44:40 +02004857 LY_TREE_FOR(child->child, child2) {
4858 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004859 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004860 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 goto error;
4862 }
Radek Krejcic071c542016-01-27 14:57:51 +01004863 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4864 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 goto error;
4866 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004867 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004868 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004869 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 goto error;
4871 }
Radek Krejcic071c542016-01-27 14:57:51 +01004872 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4873 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 goto error;
4875 }
4876 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004877 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 goto error;
4879 }
4880 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004883 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004884 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004885 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004886 if (!value) {
4887 LOGMEM;
4888 goto error;
4889 }
Radek Krejcic071c542016-01-27 14:57:51 +01004890 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4891 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004892 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004893
Radek Krejci749190d2016-02-18 16:26:25 +01004894 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004895 value = trg->rev[0].dsc;
4896 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4897 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004899
Radek Krejci749190d2016-02-18 16:26:25 +01004900 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004901 value = trg->rev[0].ref;
4902 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4903 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004904 }
4905 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004906
Radek Krejcic071c542016-01-27 14:57:51 +01004907 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004908
Radek Krejci1d82ef62015-08-07 14:44:40 +02004909 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004910 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4911 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 if (r) {
4913 goto error;
4914 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004915
Radek Krejci1d82ef62015-08-07 14:44:40 +02004916 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004917 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4918 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 if (r) {
4920 goto error;
4921 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004922
Radek Krejci1d82ef62015-08-07 14:44:40 +02004923 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004924 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4925 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004926 if (r) {
4927 goto error;
4928 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004929
Radek Krejci1d82ef62015-08-07 14:44:40 +02004930 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004931 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4932 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004933 if (r) {
4934 goto error;
4935 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004936 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4937 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004939 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004940 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004941
Radek Krejcib8f98c12016-06-24 10:30:46 +02004942 if (!submodule) {
4943 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02004944 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02004945 if (module->inc_size) {
4946 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
4947 if (!module->inc) {
4948 LOGMEM;
4949 goto error;
4950 }
4951 }
4952 if (module->imp_size) {
4953 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
4954 if (!module->imp) {
4955 LOGMEM;
4956 goto error;
4957 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004958 }
4959 }
Radek Krejcic071c542016-01-27 14:57:51 +01004960
Radek Krejcif5be10f2015-06-16 13:29:36 +02004961 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004962 * refer to them. Submodule's data nodes are stored in the
4963 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004965 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004966 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004967 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004968 goto error;
4969 }
Radek Krejci74705112015-06-05 10:25:44 +02004970
Michal Vasko345da0a2015-12-02 10:35:55 +01004971 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004972 }
Radek Krejci74705112015-06-05 10:25:44 +02004973
Radek Krejcif5be10f2015-06-16 13:29:36 +02004974 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004975 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004976
Radek Krejci1d82ef62015-08-07 14:44:40 +02004977 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004978 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004979 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004980 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004981 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004982 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004983 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004984 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004985 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004986 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004987 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004988 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004989 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004990 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004991 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004992 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004993 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004994 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004995 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004996 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 goto error;
4998 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004999
Michal Vasko345da0a2015-12-02 10:35:55 +01005000 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005002
Michal Vasko2f7925f2015-10-21 15:06:56 +02005003 /* ... and finally augments (last, so we can augment our data, for instance) */
5004 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005005 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5006 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005007
Michal Vasko2f7925f2015-10-21 15:06:56 +02005008 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005009 goto error;
5010 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005011 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005012 }
5013
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005014 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005015
5016error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 /* cleanup */
5018 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005019 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005020 }
5021 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005022 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005024 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005025 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005026 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005029}
5030
Michal Vasko0d343d12015-08-24 14:57:36 +02005031/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005032struct lys_submodule *
5033yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005034{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005036 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005038
Michal Vasko5a721fd2016-02-16 12:16:48 +01005039 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005040
Radek Krejci722b0072016-02-01 17:09:45 +01005041 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005042 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005043 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005046 /* check root element */
5047 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005048 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 goto error;
5050 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005052 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005053 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005054 goto error;
5055 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005056
Michal Vasko5a721fd2016-02-16 12:16:48 +01005057 submodule = calloc(1, sizeof *submodule);
5058 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005059 LOGMEM;
5060 goto error;
5061 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005062
Michal Vasko5a721fd2016-02-16 12:16:48 +01005063 submodule->ctx = module->ctx;
5064 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5065 submodule->type = 1;
5066 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005067
Michal Vasko5a721fd2016-02-16 12:16:48 +01005068 LOGVRB("Reading submodule \"%s\".", submodule->name);
5069 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005070 goto error;
5071 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005073 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005074 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005075
Michal Vasko5a721fd2016-02-16 12:16:48 +01005076 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005077 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005078
5079error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005080 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005081 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005082 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005083
Michal Vasko5a721fd2016-02-16 12:16:48 +01005084 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005085 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005086 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005087 }
5088
Michal Vasko5a721fd2016-02-16 12:16:48 +01005089 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005090
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005091 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5092 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005093 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005094 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005095}
5096
Michal Vasko0d343d12015-08-24 14:57:36 +02005097/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005098struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005099yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005100{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005101 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005102 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005103 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005104 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005105 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005106
Radek Krejcic071c542016-01-27 14:57:51 +01005107 unres = calloc(1, sizeof *unres);
5108 if (!unres) {
5109 LOGMEM;
5110 return NULL;
5111 }
5112
Radek Krejci722b0072016-02-01 17:09:45 +01005113 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005115 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005118 /* check root element */
5119 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005120 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005121 goto error;
5122 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005124 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005125 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005126 goto error;
5127 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005129 module = calloc(1, sizeof *module);
5130 if (!module) {
5131 LOGMEM;
5132 goto error;
5133 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 module->ctx = ctx;
5136 module->name = lydict_insert(ctx, value, strlen(value));
5137 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005138 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005139
Michal Vasko9f258e42016-02-11 11:36:27 +01005140 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005141 if (read_sub_module(module, NULL, yin, unres)) {
5142 goto error;
5143 }
5144
5145 /* resolve rest of unres items */
5146 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005147 goto error;
5148 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005149
Radek Krejciff4874d2016-03-07 12:30:50 +01005150 if (revision) {
5151 /* check revision of the parsed model */
5152 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005153 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5154 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005155 goto error;
5156 }
5157 }
5158
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005159 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005160 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005162
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005163 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005164 if (!module->implemented) {
5165 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5166 }
Michal Vasko26055752016-05-03 11:36:31 +02005167 if (lys_module_set_implement(module)) {
5168 goto error;
5169 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005170
Michal Vasko26055752016-05-03 11:36:31 +02005171 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5172 goto error;
5173 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005174 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005175 if (!module->inc[i].submodule) {
5176 continue;
5177 }
Michal Vasko26055752016-05-03 11:36:31 +02005178 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5179 goto error;
5180 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005181 }
5182 }
5183
Michal Vasko345da0a2015-12-02 10:35:55 +01005184 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005185 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005186 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005187 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005188
5189error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005191 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005192 unres_schema_free(module, &unres);
5193
5194 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005195 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005196 return NULL;
5197 }
5198
5199 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005200
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005201 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005202 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005203 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005204}