blob: 3ba83a69f91f3d1f7a76ae1cc73099b3513e154d [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>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020024#include <pcre.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025
Radek Krejci998a0b82015-08-17 13:14:36 +020026#include "libyang.h"
27#include "common.h"
28#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020029#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020030#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020032#include "resolve.h"
33#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020034#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020035
Radek Krejciadb57612016-02-16 13:34:34 +010036#define GETVAL(value, node, arg) \
37 value = lyxml_get_attr(node, arg, NULL); \
38 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010039 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010040 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010041 }
Radek Krejcice7fb782015-05-29 16:52:34 +020042
Radek Krejcic6556022016-01-27 15:16:45 +010043/* parser.c */
44int dup_prefix_check(const char *prefix, struct lys_module *module);
45
Radek Krejcib388c152015-06-04 17:03:03 +020046#define OPT_IDENT 0x01
47#define OPT_CONFIG 0x02
48#define OPT_MODULE 0x04
49#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020050#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020051static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020052
Radek Krejcib8048692015-08-05 13:36:34 +020053static 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 +020054 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020055static 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 +020056 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020057static 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 +020058 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020059static 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 +020060 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020061static 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 +020062 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020063static 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 +020064 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020065static 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 +020066 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020067static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020068 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020069static 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 +020070 int resolve, struct unres_schema *unres);
71static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020072
Michal Vasko0d343d12015-08-24 14:57:36 +020073/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020074static const char *
75read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020076{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020077 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 /* there should be <text> child */
80 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010081 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010082 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010083 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084 } else if (node->child->content) {
85 len = strlen(node->child->content);
86 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010087 } else {
88 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020090}
91
Michal Vasko0d343d12015-08-24 14:57:36 +020092/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093static int
Michal Vasko1d337e12016-02-15 12:32:04 +010094fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
95{
96 int r;
97 const char *value;
98
99 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100100 if (!(value = transform_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100101 return EXIT_FAILURE;
102 }
103
104 /* HACK - store pointer to the parent node for later status check */
105 *iffeat = (struct lys_feature *)parent;
Radek Krejci48464ed2016-03-17 15:44:09 +0100106 r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value);
Michal Vasko1d337e12016-02-15 12:32:04 +0100107 lydict_remove(parent->module->ctx, value);
108 if (!r) {
109 return EXIT_SUCCESS;
110 }
111
112error:
113 return EXIT_FAILURE;
114}
115
116/* logs directly */
117static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200118fill_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 +0200119{
Radek Krejci73adb602015-07-02 18:07:40 +0200120 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200121 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100122 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200123
Michal Vasko4cfcd252015-08-03 14:31:10 +0200124 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100125 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200126
Radek Krejci76512572015-08-04 09:47:08 +0200127 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200128 return EXIT_FAILURE;
129 }
Radek Krejci04581c62015-05-22 21:24:00 +0200130
Radek Krejci73adb602015-07-02 18:07:40 +0200131 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200132 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
133 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200134 continue;
135 }
136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200137 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100138 if (base_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100139 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200140 return EXIT_FAILURE;
141 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100142 base_flag = 1;
143
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200144 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100145 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100146 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200147 return EXIT_FAILURE;
148 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100149
Radek Krejci48464ed2016-03-17 15:44:09 +0100150 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100151 lydict_remove(module->ctx, value);
152 return EXIT_FAILURE;
153 }
154 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200155 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100156 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200157 return EXIT_FAILURE;
158 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200159 }
Radek Krejci04581c62015-05-22 21:24:00 +0200160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200161 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200162
163error:
164 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200165}
166
Michal Vasko0d343d12015-08-24 14:57:36 +0200167/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200168static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200169read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200170{
Radek Krejci73adb602015-07-02 18:07:40 +0200171 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200172 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200173
Radek Krejci73adb602015-07-02 18:07:40 +0200174 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200175 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
176 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200177 continue;
178 }
179
Radek Krejci41726f92015-06-19 13:11:05 +0200180 if (!strcmp(child->name, "description")) {
181 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100182 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200183 return EXIT_FAILURE;
184 }
185 restr->dsc = read_yin_subnode(ctx, child, "text");
186 if (!restr->dsc) {
187 return EXIT_FAILURE;
188 }
189 } else if (!strcmp(child->name, "reference")) {
190 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100191 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200192 return EXIT_FAILURE;
193 }
194 restr->ref = read_yin_subnode(ctx, child, "text");
195 if (!restr->ref) {
196 return EXIT_FAILURE;
197 }
198 } else if (!strcmp(child->name, "error-app-tag")) {
199 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200201 return EXIT_FAILURE;
202 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200203 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200204 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200205 } else if (!strcmp(child->name, "error-message")) {
206 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100207 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200208 return EXIT_FAILURE;
209 }
210 restr->emsg = read_yin_subnode(ctx, child, "value");
211 if (!restr->emsg) {
212 return EXIT_FAILURE;
213 }
214 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100215 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200216 return EXIT_FAILURE;
217 }
Radek Krejci41726f92015-06-19 13:11:05 +0200218 }
219
220 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200221
222error:
223 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200224}
225
Michal Vasko88c29542015-11-27 14:57:53 +0100226/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
227int
Radek Krejcib8048692015-08-05 13:36:34 +0200228fill_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 +0200229 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200230{
Michal Vasko1dca6882015-10-22 14:29:42 +0200231 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200232 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200233 struct lys_restr **restr;
234 struct lys_type_bit bit;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200235 struct lys_type *type_der;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200236 pcre *precomp;
237 int i, j, rc, err_offset;
Radek Krejcidc008d72016-02-17 13:12:14 +0100238 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200239 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200240 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200241
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200242 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100243 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200244 if (!value) {
245 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200246 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200247
248 i = parse_identifier(value);
249 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100250 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100251 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200252 goto error;
253 }
254 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100255 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200256 if (value[i]) {
257 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100258 name += i;
259 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100260 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100261 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200262 goto error;
263 }
Radek Krejci225376f2016-02-16 17:36:22 +0100264 ++name;
Michal Vaskoae0bce82016-06-06 15:08:18 +0200265 name = lydict_insert(module->ctx, name, 0);
266 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200267 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200268
Radek Krejci225376f2016-02-16 17:36:22 +0100269 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200270 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100271 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200272 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100273
274 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200275 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200276 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejcidc008d72016-02-17 13:12:14 +0100277 ret = EXIT_FAILURE;
278 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200279 }
280 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;
455 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100456 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200457 goto error;
458 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200459 }
460
461 /* mandatory sub-statement(s) check */
462 if (!type->info.dec64.dig && !type->der->type.der) {
463 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100464 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200465 goto error;
466 }
Radek Krejci7511f402015-07-10 09:56:30 +0200467 if (type->info.dec64.dig && type->der->type.der) {
468 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100469 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200470 goto error;
471 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200472 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200475 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200476
Radek Krejci994b6f62015-06-18 16:47:27 +0200477 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200478 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200479 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
480 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100481 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200482 continue;
483 }
484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200485 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200486 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200487 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100488 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200489 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200490 }
491 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200492 if (!type->der->type.der && !type->info.enums.count) {
493 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100494 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200495 goto error;
496 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200497 if (type->der->type.der && type->info.enums.count) {
498 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100499 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200500 goto error;
501 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200502
Radek Krejci1574a8d2015-08-03 14:16:52 +0200503 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100504 if (!type->info.enums.enm) {
505 LOGMEM;
506 goto error;
507 }
Radek Krejci73adb602015-07-02 18:07:40 +0200508 v = 0;
509 i = -1;
510 LY_TREE_FOR(yin->child, next) {
511 i++;
512
513 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100514 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100515 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
516 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100517 goto error;
518 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200519 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200520 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200521 type->info.enums.count = i + 1;
522 goto error;
523 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200526 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200527 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100528 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200529 type->info.enums.count = i + 1;
530 goto error;
531 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200533 /* check the name uniqueness */
534 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200535 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100536 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200537 type->info.enums.count = i + 1;
538 goto error;
539 }
540 }
Radek Krejci04581c62015-05-22 21:24:00 +0200541
Radek Krejci0d70c372015-07-02 16:23:10 +0200542 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200543 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200544 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
545 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200546 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200548
Radek Krejci0d70c372015-07-02 16:23:10 +0200549 if (!strcmp(node->name, "value")) {
550 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200551 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200552
553 /* range check */
554 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100555 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200556 type->info.enums.count = i + 1;
557 goto error;
558 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200559 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200560
561 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200562 if (type->info.enums.enm[i].value > v) {
563 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200564 v++;
565 } else {
566 /* check that the value is unique */
567 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200568 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100569 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100570 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200571 type->info.enums.count = i + 1;
572 goto error;
573 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200574 }
575 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200576 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100577 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200578 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200579 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 }
581 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200582 /* assign value automatically */
583 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100584 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585 type->info.enums.count = i + 1;
586 goto error;
587 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200588 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100589 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 v++;
591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 }
593 break;
594
595 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200596 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597
598 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200599 LY_TREE_FOR_SAFE(yin->child, next, node) {
600 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
601 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100602 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200603 continue;
604 }
605
Michal Vaskoe29c6622015-11-27 15:02:31 +0100606 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100607 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200608 goto error;
609 }
610 }
611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200613 if (type->der->type.der) {
614 /* this is just a derived type with no base specified/required */
615 break;
616 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100617 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 goto error;
619 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100621 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 goto error;
623 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200624 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100625 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100626 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100627 if (!value) {
628 goto error;
629 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100630 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100631 lydict_remove(module->ctx, value);
632
633 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200634 goto error;
635 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 break;
637
638 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200639 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200640 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200641 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
642 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200643 continue;
644 }
645
Radek Krejciaf351422015-06-19 14:49:38 +0200646 if (!strcmp(node->name, "require-instance")) {
647 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100648 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200649 goto error;
650 }
651 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200652 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200653 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200654 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200655 type->info.inst.req = -1;
656 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100657 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200658 goto error;
659 }
660 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100661 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200662 goto error;
663 }
Radek Krejciaf351422015-06-19 14:49:38 +0200664 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200666 break;
667
Radek Krejcif2860132015-06-20 12:37:20 +0200668 case LY_TYPE_BINARY:
669 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200670 case LY_TYPE_INT8:
671 case LY_TYPE_INT16:
672 case LY_TYPE_INT32:
673 case LY_TYPE_INT64:
674 case LY_TYPE_UINT8:
675 case LY_TYPE_UINT16:
676 case LY_TYPE_UINT32:
677 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200678 /* RFC 6020 9.2.4 - range */
679
680 /* length and range are actually the same restriction, so process
681 * them by this common code, we just need to differ the name and
682 * structure where the information will be stored
683 */
684 if (type->base == LY_TYPE_BINARY) {
685 restr = &type->info.binary.length;
686 name = "length";
687 } else {
688 restr = &type->info.num.range;
689 name = "range";
690 }
691
Radek Krejci73adb602015-07-02 18:07:40 +0200692 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200693 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
694 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200695 continue;
696 }
697
Radek Krejcif2860132015-06-20 12:37:20 +0200698 if (!strcmp(node->name, name)) {
699 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100700 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200701 goto error;
702 }
703
704 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200705 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100706 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200707 goto error;
708 }
709 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100710 if (!(*restr)) {
711 LOGMEM;
712 goto error;
713 }
Radek Krejcif2860132015-06-20 12:37:20 +0200714 (*restr)->expr = lydict_insert(module->ctx, value, 0);
715
716 /* get possible substatements */
717 if (read_restr_substmt(module->ctx, *restr, node)) {
718 goto error;
719 }
720 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200722 goto error;
723 }
Radek Krejcif2860132015-06-20 12:37:20 +0200724 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 break;
726
727 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200728 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200729 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200730 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
731 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200732 continue;
733 }
734
Michal Vasko88c29542015-11-27 14:57:53 +0100735 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200736 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100737 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200738 goto error;
739 }
740
741 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200742 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100743 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200744 if (!type->info.lref.path) {
745 goto error;
746 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100747 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200748 goto error;
749 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200750
Radek Krejcidc4c1412015-06-19 15:39:54 +0200751 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100752 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200753 goto error;
754 }
Radek Krejci73adb602015-07-02 18:07:40 +0200755 }
756
Michal Vasko88c29542015-11-27 14:57:53 +0100757 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100758 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200759 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200760 } else if (type->der->type.der && parent) {
761 for (type_der = &type->der->type; !type_der->info.lref.path && type_der->der; type_der = &type_der->der->type);
762 assert(type_der->info.lref.path && type_der->info.lref.target);
763 /* add pointer to leafref target, only on leaves (not in typedefs) */
764 if (lys_leaf_add_leafref_target(type_der->info.lref.target, (struct lys_node *)type->parent)) {
765 goto error;
766 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 break;
769
770 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200771 /* RFC 6020 9.4.4 - length */
772 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200773 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200774 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200775 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
776 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100777 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200778 continue;
779 }
780
Radek Krejci3733a802015-06-19 13:43:21 +0200781 if (!strcmp(node->name, "length")) {
782 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100783 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200784 goto error;
785 }
786
787 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200788 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100789 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200790 goto error;
791 }
792 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100793 if (!type->info.str.length) {
794 LOGMEM;
795 goto error;
796 }
Radek Krejci3733a802015-06-19 13:43:21 +0200797 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
798
Radek Krejci5fbc9162015-06-19 14:11:11 +0200799 /* get possible sub-statements */
800 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200801 goto error;
802 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100803 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200804 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200805 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200806 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100807 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200808 goto error;
809 }
810 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200811 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200812 if (i) {
813 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100814 if (!type->info.str.patterns) {
815 LOGMEM;
816 goto error;
817 }
Radek Krejci73adb602015-07-02 18:07:40 +0200818 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100819 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200820
821 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200822 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
823 if (!precomp) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100824 LOGVAL(LYE_INREGEX, LY_VLOG_NONE, NULL, value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200825 free(type->info.str.patterns);
826 goto error;
827 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200828 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200829
Radek Krejci73adb602015-07-02 18:07:40 +0200830 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200831
832 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100833 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200834 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200835 goto error;
836 }
Radek Krejci73adb602015-07-02 18:07:40 +0200837 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200838 }
839 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200840 break;
841
842 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200843 /* RFC 6020 7.4 - type */
844 /* count number of types in union */
845 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200846 LY_TREE_FOR_SAFE(yin->child, next, node) {
847 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
848 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100849 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200850 continue;
851 }
852
Radek Krejcie4c366b2015-07-02 10:11:31 +0200853 if (!strcmp(node->name, "type")) {
854 i++;
855 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100856 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200857 goto error;
858 }
859 }
860
861 if (!i) {
862 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100863 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200864 break;
865 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100866 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200867 goto error;
868 }
869
870 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200871 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100872 if (!type->info.uni.types) {
873 LOGMEM;
874 goto error;
875 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200876 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200877 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100878 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100879 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
880 if (!rc) {
881 type->info.uni.count++;
882
883 /* union's type cannot be empty or leafref */
884 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100885 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100886 rc = -1;
887 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100888 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100889 rc = -1;
890 }
891 }
892 if (rc) {
893 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
894 for (i = 0; i < type->info.uni.count; ++i) {
895 lys_type_free(module->ctx, &type->info.uni.types[i]);
896 }
897 free(type->info.uni.types);
898 type->info.uni.types = NULL;
899 type->info.uni.count = 0;
900
901 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100902 ret = EXIT_FAILURE;
903 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100904 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200905 goto error;
906 }
Michal Vasko88c29542015-11-27 14:57:53 +0100907 }
908 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200909
Michal Vasko88c29542015-11-27 14:57:53 +0100910 case LY_TYPE_BOOL:
911 case LY_TYPE_EMPTY:
912 /* no sub-statement allowed */
913 LY_TREE_FOR(yin->child, node) {
914 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100915 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200916 goto error;
917 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 break;
920
921 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100922 LOGINT;
923 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200924 }
925
926 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200927
928error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100929 if (type->module_name) {
930 lydict_remove(module->ctx, type->module_name);
931 type->module_name = NULL;
932 }
933 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200934}
935
Michal Vasko0d343d12015-08-24 14:57:36 +0200936/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200938fill_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 +0200939{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100941 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100942 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100945 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 goto error;
947 }
948 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100951 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 goto error;
953 }
Radek Krejcieac35532015-05-31 19:09:15 +0200954
Michal Vasko88c29542015-11-27 14:57:53 +0100955 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200956 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
957 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200958 continue;
959 }
960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200961 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100962 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100963 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 goto error;
965 }
Michal Vasko88c29542015-11-27 14:57:53 +0100966 /* HACK for unres */
967 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100968 tpdf->type.parent = tpdf;
Radek Krejci48464ed2016-03-17 15:44:09 +0100969 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent)) {
Radek Krejci73adb602015-07-02 18:07:40 +0200970 goto error;
971 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200972 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 } else if (!strcmp(node->name, "default")) {
974 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100975 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200976 goto error;
977 }
978 GETVAL(value, node, "value");
979 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
980 } else if (!strcmp(node->name, "units")) {
981 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100982 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 goto error;
984 }
985 GETVAL(value, node, "name");
986 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
987 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100988 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 goto error;
990 }
991 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200994 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100995 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 goto error;
997 }
Radek Krejcieac35532015-05-31 19:09:15 +0200998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001000 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001001 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001002 goto error;
1003 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001007
1008error:
1009
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001010 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001011}
1012
Michal Vasko0d343d12015-08-24 14:57:36 +02001013/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001014static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001015fill_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 +02001016{
1017 const char *value;
1018 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001019 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001020
Radek Krejcib05774c2015-06-18 13:52:59 +02001021 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001022 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001023 goto error;
1024 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001025 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001026 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001027
Radek Krejci76512572015-08-04 09:47:08 +02001028 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001029 goto error;
1030 }
1031
1032 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001033 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1034 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001035 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001036 continue;
1037 }
1038
Radek Krejci3cf9e222015-06-18 11:37:50 +02001039 if (!strcmp(child->name, "if-feature")) {
1040 c++;
1041 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001042 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001043 goto error;
1044 }
1045 }
1046
1047 if (c) {
1048 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001049 if (!f->features) {
1050 LOGMEM;
1051 goto error;
1052 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001053 }
Radek Krejci73adb602015-07-02 18:07:40 +02001054 LY_TREE_FOR(yin->child, child) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001055 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001056 f->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001057 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001058 goto error;
1059 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001060 }
1061
Radek Krejci3cf9e222015-06-18 11:37:50 +02001062 return EXIT_SUCCESS;
1063
1064error:
1065
1066 return EXIT_FAILURE;
1067}
1068
Michal Vasko0d343d12015-08-24 14:57:36 +02001069/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070static int
Radek Krejcib8048692015-08-05 13:36:34 +02001071fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001072{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001073 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001076 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001077 if (!must->expr) {
1078 goto error;
1079 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001080 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001081 goto error;
1082 }
Radek Krejci800af702015-06-02 13:46:01 +02001083
Radek Krejci41726f92015-06-19 13:11:05 +02001084 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001085
Michal Vasko77dc5652016-02-15 12:32:42 +01001086error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001087 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001088}
1089
Radek Krejci581ce772015-11-10 17:22:40 +01001090static int
Michal Vasko88c29542015-11-27 14:57:53 +01001091fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1092 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001093{
1094 int i, j;
1095 const char *value, *vaux;
1096
1097 /* get unique value (list of leafs supposed to be unique */
1098 GETVAL(value, yin, "tag");
1099
1100 /* count the number of unique leafs in the value */
1101 vaux = value;
1102 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001103 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001104 while (isspace(*vaux)) {
1105 vaux++;
1106 }
1107 }
1108 unique->expr_size++;
1109 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001110 if (!unique->expr) {
1111 LOGMEM;
1112 goto error;
1113 }
Radek Krejci581ce772015-11-10 17:22:40 +01001114
1115 for (i = 0; i < unique->expr_size; i++) {
1116 vaux = strpbrk(value, " \t\n");
1117 if (!vaux) {
1118 /* the last token, lydict_insert() will count its size on its own */
1119 vaux = value;
1120 }
1121
1122 /* store token into unique structure */
1123 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1124
1125 /* check that the expression does not repeat */
1126 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001127 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001128 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1129 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001130 goto error;
1131 }
1132 }
1133
1134 /* try to resolve leaf */
1135 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001136 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1137 goto error;
1138 }
Radek Krejci581ce772015-11-10 17:22:40 +01001139 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001140 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001141 goto error;
1142 }
1143 }
1144
1145 /* move to next token */
1146 value = vaux;
1147 while(isspace(*value)) {
1148 value++;
1149 }
1150 }
1151
1152 return EXIT_SUCCESS;
1153
1154error:
1155 return EXIT_FAILURE;
1156}
1157
Michal Vasko0d343d12015-08-24 14:57:36 +02001158/* logs directly
1159 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001160 * type: 0 - min, 1 - max
1161 */
1162static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001163deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001164{
1165 const char *value;
1166 char *endptr;
1167 unsigned long val;
1168 uint32_t *ui32val;
1169
Michal Vaskof7e57d52016-03-07 11:31:09 +01001170 /* del min/max is forbidden */
1171 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001172 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001173 goto error;
1174 }
1175
Radek Krejcieb00f512015-07-01 16:44:58 +02001176 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001177 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001178 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001179 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001180 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001181 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001182 }
Radek Krejci76512572015-08-04 09:47:08 +02001183 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001184 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001185 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001186 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001187 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001188 }
1189 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001190 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1191 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001192 goto error;
1193 }
1194
1195 GETVAL(value, node, "value");
1196 while (isspace(value[0])) {
1197 value++;
1198 }
1199
Radek Krejci0d7b2472016-02-12 11:11:03 +01001200 if (type && !strcmp(value, "unbounded")) {
1201 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001202 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001203 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001204 /* convert it to uint32_t */
1205 errno = 0;
1206 endptr = NULL;
1207 val = strtoul(value, &endptr, 10);
1208 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001209 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001210 goto error;
1211 }
1212 if (type) {
1213 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001214 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001215 } else {
1216 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001217 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001218 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001219 }
1220
1221 if (d->mod == LY_DEVIATE_ADD) {
1222 /* check that there is no current value */
1223 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001224 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1225 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001226 goto error;
1227 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001228 } else if (d->mod == LY_DEVIATE_RPL) {
1229 /* unfortunately, there is no way to check reliably that there
1230 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001231 }
1232
Michal Vaskof7e57d52016-03-07 11:31:09 +01001233 /* add (already checked) and replace */
1234 /* set new value specified in deviation */
1235 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001236
1237 return EXIT_SUCCESS;
1238
1239error:
1240
1241 return EXIT_FAILURE;
1242}
1243
Michal Vasko0d343d12015-08-24 14:57:36 +02001244/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001245static int
Michal Vasko88c29542015-11-27 14:57:53 +01001246fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1247 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001248{
1249 const char *value, **stritem;
1250 struct lyxml_elem *next, *child, *develem;
1251 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001252 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001253 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001254 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001255 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001256 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001257 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001258 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001259 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001260 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001261 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001262 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001263 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001264
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001265 ctx = module->ctx;
1266
Radek Krejcieb00f512015-07-01 16:44:58 +02001267 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001268 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001269 if (!dev->target_name) {
1270 goto error;
1271 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001272
1273 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001274 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1275 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001276 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001277 goto error;
1278 }
Radek Krejcic4283442016-04-22 09:19:27 +02001279 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001280 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1281 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001282 goto error;
1283 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001284 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001285
1286 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001287 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1288 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001289 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001290 continue;
1291 }
1292
Radek Krejcieb00f512015-07-01 16:44:58 +02001293 if (!strcmp(child->name, "description")) {
1294 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001295 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001296 goto error;
1297 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001298 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001299 if (!dev->dsc) {
1300 goto error;
1301 }
1302 } else if (!strcmp(child->name, "reference")) {
1303 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001304 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001305 goto error;
1306 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001307 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001308 if (!dev->ref) {
1309 goto error;
1310 }
1311 } else if (!strcmp(child->name, "deviate")) {
1312 c_dev++;
1313
Michal Vasko345da0a2015-12-02 10:35:55 +01001314 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001315 * further processed later
1316 */
1317 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001318
Radek Krejcieb00f512015-07-01 16:44:58 +02001319 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001320 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001321 goto error;
1322 }
1323
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001324 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001325 }
1326
1327 if (c_dev) {
1328 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001329 if (!dev->deviate) {
1330 LOGMEM;
1331 goto error;
1332 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001333 }
1334
1335 LY_TREE_FOR(yin->child, develem) {
1336 /* init */
1337 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001338 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001339 c_must = 0;
1340 c_uniq = 0;
1341
1342 /* get deviation type */
1343 GETVAL(value, develem, "value");
1344 if (!strcmp(value, "not-supported")) {
1345 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1346 /* no property expected in this case */
1347 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001348 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001349 goto error;
1350 }
1351
Radek Krejci5b917642015-07-02 09:03:13 +02001352 /* and neither any other deviate statement is expected,
1353 * not-supported deviation must be the only deviation of the target
1354 */
1355 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001356 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1357 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001358 goto error;
1359 }
1360
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001361 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001362 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1363 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1364 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001365 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1366 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001367 goto error;
1368 }
1369 }
1370 }
Radek Krejci5b917642015-07-02 09:03:13 +02001371
Michal Vaskoff006c12016-02-17 11:15:19 +01001372 /* unlink and store the original node */
1373 lys_node_unlink(dev_target);
1374 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001375
Radek Krejci5b917642015-07-02 09:03:13 +02001376 dev->deviate_size = 1;
1377 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001378 } else if (!strcmp(value, "add")) {
1379 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1380 } else if (!strcmp(value, "replace")) {
1381 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1382 } else if (!strcmp(value, "delete")) {
1383 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1384 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001385 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001386 goto error;
1387 }
1388 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001389 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001390
Michal Vaskoff006c12016-02-17 11:15:19 +01001391 /* store a shallow copy of the original node */
1392 if (!dev->orig_node) {
1393 memset(&tmp_unres, 0, sizeof tmp_unres);
1394 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1395 /* just to be safe */
1396 if (tmp_unres.count) {
1397 LOGINT;
1398 goto error;
1399 }
1400 }
1401
Radek Krejcieb00f512015-07-01 16:44:58 +02001402 /* process deviation properties */
1403 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001404 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1405 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001406 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001407 continue;
1408 }
1409
Radek Krejcieb00f512015-07-01 16:44:58 +02001410 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001411 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001412 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001413 goto error;
1414 }
1415
1416 /* for we deviate from RFC 6020 and allow config property even it is/is not
1417 * specified in the target explicitly since config property inherits. So we expect
1418 * that config is specified in every node. But for delete, we check that the value
1419 * is the same as here in deviation
1420 */
1421 GETVAL(value, child, "value");
1422 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001423 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001424 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001425 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001426 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001427 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001428 goto error;
1429 }
1430
1431 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001432 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001433 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001434 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 } else { /* add and replace are the same in this case */
1436 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001437 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001438
1439 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001440 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001441 }
1442 } else if (!strcmp(child->name, "default")) {
1443 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001444 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001445 goto error;
1446 }
1447 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001448 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001449
Michal Vasko60f4b452016-02-12 11:02:55 +01001450 if (dev_target->nodetype == LYS_CHOICE) {
1451 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001452
1453 if (d->mod == LY_DEVIATE_ADD) {
1454 /* check that there is no current value */
1455 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001456 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1457 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001458 goto error;
1459 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001460 /* check collision with mandatory */
1461 if (choice->flags & LYS_MAND_TRUE) {
1462 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1463 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1464 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1465 goto error;
1466 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001467 } else if (d->mod == LY_DEVIATE_RPL) {
1468 /* check that there was a value before */
1469 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001470 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1471 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001472 goto error;
1473 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001474 }
1475
Michal Vasko3edeaf72016-02-11 13:17:43 +01001476 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001477 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001478 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001479 goto error;
1480 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001481 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001482 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001483 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1484 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001485 goto error;
1486 }
1487 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001488 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001489 if (!choice->dflt) {
1490 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001491 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001492 goto error;
1493 }
1494 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001495 } else if (dev_target->nodetype == LYS_LEAF) {
1496 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001497
1498 if (d->mod == LY_DEVIATE_ADD) {
1499 /* check that there is no current value */
1500 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001501 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1502 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001503 goto error;
1504 }
Radek Krejci841ec082016-04-05 13:05:17 +02001505 /* check collision with mandatory */
1506 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001507 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001508 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001509 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001510 goto error;
1511 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 }
1513
1514 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001515 if (!leaf->dflt || !ly_strequal(leaf->dflt, d->dflt, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001516 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1517 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001518 goto error;
1519 }
1520 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001521 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001522 leaf->dflt = NULL;
1523 } else { /* add (already checked) and replace */
1524 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001525 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001526
1527 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001528 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001529
1530 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1531 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1532 if (!leaf_dflt_check) {
1533 LOGMEM;
1534 goto error;
1535 }
1536 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001537 }
1538 } else {
1539 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001540 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1541 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001542 goto error;
1543 }
1544 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001545 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001546 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001547 goto error;
1548 }
1549
1550 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001551 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001552 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1553 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 goto error;
1555 }
1556
1557 GETVAL(value, child, "value");
1558 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001559 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001560 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001561 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001563 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001564 goto error;
1565 }
1566
1567 if (d->mod == LY_DEVIATE_ADD) {
1568 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001569 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001570 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1571 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001572 goto error;
1573 }
Radek Krejci841ec082016-04-05 13:05:17 +02001574 /* check collision with default-stmt */
1575 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001576 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001577 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001578 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001579 goto error;
1580 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001581
Michal Vasko21be1b32016-03-07 12:31:34 +01001582 dev_target->flags |= d->flags & LYS_MAND_MASK;
1583 } else if (d->mod == LY_DEVIATE_RPL) {
1584 /* check that there was a value before */
1585 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001586 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1587 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001588 goto error;
1589 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001590
Michal Vasko21be1b32016-03-07 12:31:34 +01001591 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001592 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001593 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001594 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001595 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001596 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001597 }
1598 } else if (!strcmp(child->name, "min-elements")) {
1599 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001600 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001601 goto error;
1602 }
1603 f_min = 1;
1604
Michal Vasko60f4b452016-02-12 11:02:55 +01001605 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 goto error;
1607 }
1608 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001609 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001610 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001611 goto error;
1612 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001613 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001614
Michal Vasko60f4b452016-02-12 11:02:55 +01001615 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001616 goto error;
1617 }
1618 } else if (!strcmp(child->name, "must")) {
1619 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001620 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001621 continue;
1622 } else if (!strcmp(child->name, "type")) {
1623 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001624 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001625 goto error;
1626 }
1627
Michal Vaskof7e57d52016-03-07 11:31:09 +01001628 /* add, del type is forbidden */
1629 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001630 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001631 goto error;
1632 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001633 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001634 goto error;
1635 }
1636
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001638 if (dev_target->nodetype == LYS_LEAF) {
1639 t = &((struct lys_node_leaf *)dev_target)->type;
1640 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1641 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001643 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1644 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 goto error;
1646 }
1647
Radek Krejcieb00f512015-07-01 16:44:58 +02001648 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001649 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001650 /* HACK for unres */
1651 t->der = (struct lys_tpdf *)child;
Radek Krejci48464ed2016-03-17 15:44:09 +01001652 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 goto error;
1654 }
1655 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001656
1657 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1658 if (dev_target->nodetype == LYS_LEAF) {
1659 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1660 if (!leaf_dflt_check) {
1661 LOGMEM;
1662 goto error;
1663 }
1664 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1665 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 } else if (!strcmp(child->name, "unique")) {
1667 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001668 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001669 continue;
1670 } else if (!strcmp(child->name, "units")) {
1671 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001672 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001673 goto error;
1674 }
1675
1676 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001677 if (dev_target->nodetype == LYS_LEAFLIST) {
1678 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1679 } else if (dev_target->nodetype == LYS_LEAF) {
1680 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001681 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001682 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1683 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001684 goto error;
1685 }
1686
1687 /* get units value */
1688 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001689 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001690
1691 /* apply to target */
1692 if (d->mod == LY_DEVIATE_ADD) {
1693 /* check that there is no current value */
1694 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001695 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1696 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 goto error;
1698 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001699
Michal Vasko21be1b32016-03-07 12:31:34 +01001700 *stritem = lydict_insert(ctx, value, 0);
1701 } else if (d->mod == LY_DEVIATE_RPL) {
1702 /* check that there was a value before */
1703 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1705 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001706 goto error;
1707 }
1708
1709 lydict_remove(ctx, *stritem);
1710 *stritem = lydict_insert(ctx, value, 0);
1711 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001712 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001713 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001714 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1715 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 goto error;
1717 }
1718 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001719 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001720 }
1721 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001722 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001723 goto error;
1724 }
1725
Michal Vasko88c29542015-11-27 14:57:53 +01001726 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 }
1728
1729 if (c_must) {
1730 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001731 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001732 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001733 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1734 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001735 break;
Radek Krejci76512572015-08-04 09:47:08 +02001736 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001737 trg_must = &((struct lys_node_container *)dev_target)->must;
1738 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001739 break;
Radek Krejci76512572015-08-04 09:47:08 +02001740 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001741 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1742 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001743 break;
Radek Krejci76512572015-08-04 09:47:08 +02001744 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001745 trg_must = &((struct lys_node_list *)dev_target)->must;
1746 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 break;
Radek Krejci76512572015-08-04 09:47:08 +02001748 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001749 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1750 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001751 break;
1752 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001753 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1754 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001755 goto error;
1756 }
1757
1758 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001759 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001760 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001761 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001762 } else if (d->mod == LY_DEVIATE_ADD) {
1763 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001764 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001765 if (!d->must) {
1766 LOGMEM;
1767 goto error;
1768 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001769 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001770 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 d->must_size = c_must;
1772 } else { /* LY_DEVIATE_DEL */
1773 d->must = calloc(c_must, sizeof *d->must);
1774 }
Michal Vasko253035f2015-12-17 16:58:13 +01001775 if (!d->must) {
1776 LOGMEM;
1777 goto error;
1778 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 }
1780 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001781 /* replace unique is forbidden */
1782 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001783 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001784 goto error;
1785 }
1786
Radek Krejcieb00f512015-07-01 16:44:58 +02001787 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001788 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001789 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1790 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 goto error;
1792 }
1793
Michal Vasko60f4b452016-02-12 11:02:55 +01001794 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001795 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001796 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001797 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 list->unique = d->unique;
1799 d->unique = &list->unique[list->unique_size];
1800 d->unique_size = c_uniq;
1801 } else { /* LY_DEVIATE_DEL */
1802 d->unique = calloc(c_uniq, sizeof *d->unique);
1803 }
Michal Vasko253035f2015-12-17 16:58:13 +01001804 if (!d->unique) {
1805 LOGMEM;
1806 goto error;
1807 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001808 }
1809
1810 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001811 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001812 if (!strcmp(child->name, "must")) {
1813 if (d->mod == LY_DEVIATE_DEL) {
1814 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1815 goto error;
1816 }
1817
1818 /* find must to delete, we are ok with just matching conditions */
1819 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001820 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001821 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001822 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 /* ... and maintain the array */
1824 (*trg_must_size)--;
1825 if (i != *trg_must_size) {
1826 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1827 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1828 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1829 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1830 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1831 }
1832 if (!(*trg_must_size)) {
1833 free(*trg_must);
1834 *trg_must = NULL;
1835 } else {
1836 (*trg_must)[*trg_must_size].expr = NULL;
1837 (*trg_must)[*trg_must_size].dsc = NULL;
1838 (*trg_must)[*trg_must_size].ref = NULL;
1839 (*trg_must)[*trg_must_size].eapptag = NULL;
1840 (*trg_must)[*trg_must_size].emsg = NULL;
1841 }
1842
1843 i = -1; /* set match flag */
1844 break;
1845 }
1846 }
1847 d->must_size++;
1848 if (i != -1) {
1849 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001850 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001851 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001852 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001853 goto error;
1854 }
1855 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001856 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1857 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001858 goto error;
1859 }
1860 (*trg_must_size)++;
1861 }
1862 } else if (!strcmp(child->name, "unique")) {
1863 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001864 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001865 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001866 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001867 goto error;
1868 }
1869
1870 /* find unique structures to delete */
1871 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001872 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001873 continue;
1874 }
1875
Radek Krejci581ce772015-11-10 17:22:40 +01001876 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001877 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001878 break;
1879 }
1880 }
1881
Radek Krejci581ce772015-11-10 17:22:40 +01001882 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001883 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001884 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001885 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001886 }
1887 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001888 /* ... and maintain the array */
1889 list->unique_size--;
1890 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001891 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1892 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001893 }
1894
1895 if (!list->unique_size) {
1896 free(list->unique);
1897 list->unique = NULL;
1898 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001899 list->unique[list->unique_size].expr_size = 0;
1900 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001901 }
1902
1903 i = -1; /* set match flag */
1904 break;
1905 }
1906 }
1907
1908 d->unique_size++;
1909 if (i != -1) {
1910 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001911 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1912 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001913 goto error;
1914 }
1915 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001916 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001917 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001918 list->unique_size++;
1919 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001920 goto error;
1921 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 }
1923 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001924 }
1925 }
1926
Michal Vasko43a1feb2016-03-07 12:03:02 +01001927 /* now check whether default value, if any, matches the type */
1928 for (i = 0; i < leaf_dflt_check_count; ++i) {
1929 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001930 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 +01001931 if (rc == -1) {
1932 goto error;
1933 } else if (rc == EXIT_FAILURE) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001934 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1935 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 +01001936 goto error;
1937 }
1938 }
1939 }
1940 free(leaf_dflt_check);
1941
Radek Krejcieb00f512015-07-01 16:44:58 +02001942 return EXIT_SUCCESS;
1943
1944error:
Michal Vasko34867132016-03-11 10:26:38 +01001945 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001946 return EXIT_FAILURE;
1947}
1948
Michal Vasko0d343d12015-08-24 14:57:36 +02001949/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001950static int
Radek Krejcib8048692015-08-05 13:36:34 +02001951fill_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 +02001952 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001953{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001954 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001956 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001957 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001958
Michal Vasko591e0b22015-08-13 13:53:43 +02001959 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001960 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001961 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02001962 if (!aug->target_name) {
1963 goto error;
1964 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001966
Michal Vasko1d87a922015-08-21 12:57:16 +02001967 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001968 goto error;
1969 }
1970
1971 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001972 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1973 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001974 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001975 continue;
1976 }
1977
Radek Krejci3cf9e222015-06-18 11:37:50 +02001978 if (!strcmp(child->name, "if-feature")) {
1979 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001981 } else if (!strcmp(child->name, "when")) {
1982 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001983 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001984 goto error;
1985 }
1986
1987 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001988 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001989 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001990 goto error;
1991 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001992 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001993 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001994
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 /* check allowed data sub-statements */
1996 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001997 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001998 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001999 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002000 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002003 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002004 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002005 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002007 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 } else if (!strcmp(child->name, "case")) {
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, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002013 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002014 goto error;
2015 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016
Radek Krejci1d82ef62015-08-07 14:44:40 +02002017 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002018 goto error;
2019 }
2020
Radek Krejci1d82ef62015-08-07 14:44:40 +02002021 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002022 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002023 }
2024
2025 if (c) {
2026 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002027 if (!aug->features) {
2028 LOGMEM;
2029 goto error;
2030 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002031 }
2032
2033 LY_TREE_FOR_SAFE(yin->child, next, child) {
2034 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002035 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002036 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002037 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002038 goto error;
2039 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002040 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002041 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002042 }
2043
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002044 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002045 * connected to the tree and adjusted (if possible right now).
2046 * However, if this is augment in a uses, it gets resolved
2047 * when the uses does and cannot be resolved now for sure
2048 * (the grouping was not yet copied into uses).
2049 */
2050 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002051 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002052 goto error;
2053 }
Michal Vasko49291b32015-08-06 09:49:41 +02002054 }
Radek Krejci106efc02015-06-10 14:36:27 +02002055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002057
2058error:
2059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002061}
2062
Michal Vasko0d343d12015-08-24 14:57:36 +02002063/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064static int
Michal Vasko0d204592015-10-07 09:50:04 +02002065fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002066{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 struct lyxml_elem *sub, *next;
2068 const char *value;
2069 char *endptr;
2070 int f_mand = 0, f_min = 0, f_max = 0;
2071 int c_must = 0;
2072 int r;
2073 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002074
Radek Krejci76512572015-08-04 09:47:08 +02002075 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 goto error;
2077 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002078
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002079 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002080 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002081 if (!rfn->target_name) {
2082 goto error;
2083 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002086 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2087 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002088 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002089 continue;
2090 }
2091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 /* limited applicability */
2093 if (!strcmp(sub->name, "default")) {
2094 /* leaf or choice */
2095 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002096 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 goto error;
2098 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 /* check possibility of statements combination */
2101 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002102 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002104 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2105 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 goto error;
2107 }
2108 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002109 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 GETVAL(value, sub, "value");
2113 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2114 } else if (!strcmp(sub->name, "mandatory")) {
2115 /* leaf, choice or anyxml */
2116 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002117 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 goto error;
2119 }
2120 /* just checking the flags in leaf is not sufficient, we would allow
2121 * multiple mandatory statements with the "false" value
2122 */
2123 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 /* check possibility of statements combination */
2126 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002127 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002129 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 goto error;
2132 }
2133 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002134 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 GETVAL(value, sub, "value");
2138 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002139 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002141 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002143 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 goto error;
2145 }
2146 } else if (!strcmp(sub->name, "min-elements")) {
2147 /* list or leaf-list */
2148 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002149 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 goto error;
2151 }
2152 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 /* check possibility of statements combination */
2155 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002156 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002158 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2159 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 goto error;
2161 }
2162 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002163 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 GETVAL(value, sub, "value");
2167 while (isspace(value[0])) {
2168 value++;
2169 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 /* convert it to uint32_t */
2172 errno = 0;
2173 endptr = NULL;
2174 val = strtoul(value, &endptr, 10);
2175 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002176 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 goto error;
2178 }
2179 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002180 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 } else if (!strcmp(sub->name, "max-elements")) {
2182 /* list or leaf-list */
2183 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002184 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 goto error;
2186 }
2187 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 /* check possibility of statements combination */
2190 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002191 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002193 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2194 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 goto error;
2196 }
2197 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002198 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 GETVAL(value, sub, "value");
2202 while (isspace(value[0])) {
2203 value++;
2204 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002205
Radek Krejci0d7b2472016-02-12 11:11:03 +01002206 if (!strcmp(value, "unbounded")) {
2207 rfn->mod.list.max = 0;
2208 } else {
2209 /* convert it to uint32_t */
2210 errno = 0;
2211 endptr = NULL;
2212 val = strtoul(value, &endptr, 10);
2213 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002214 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002215 goto error;
2216 }
2217 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002219 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 } else if (!strcmp(sub->name, "presence")) {
2221 /* container */
2222 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002223 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 goto error;
2225 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 /* check possibility of statements combination */
2228 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002229 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002231 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2232 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 goto error;
2234 }
2235 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002236 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 GETVAL(value, sub, "value");
2240 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2241 } else if (!strcmp(sub->name, "must")) {
2242 /* leaf-list, list, container or anyxml */
2243 /* check possibility of statements combination */
2244 if (rfn->target_type) {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002245 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002247 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2248 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 goto error;
2250 }
2251 } else {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002252 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002256 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002259 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 goto error;
2261 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002262
Michal Vasko345da0a2015-12-02 10:35:55 +01002263 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 /* process nodes with cardinality of 0..n */
2267 if (c_must) {
2268 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002269 if (!rfn->must) {
2270 LOGMEM;
2271 goto error;
2272 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 }
Radek Krejci73adb602015-07-02 18:07:40 +02002274 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002275 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2276 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002277 if (r) {
2278 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002283
2284error:
2285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002287}
2288
Michal Vasko0d343d12015-08-24 14:57:36 +02002289/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290static int
Radek Krejcib8048692015-08-05 13:36:34 +02002291fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002292{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 struct lyxml_elem *child;
2294 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002297 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2298 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002299 continue;
2300 }
2301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 if (!strcmp(child->name, "prefix")) {
2303 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002304 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 goto error;
2306 }
2307 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2308 } else if (!strcmp(child->name, "revision-date")) {
2309 if (imp->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002310 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 goto error;
2312 }
2313 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002314 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 goto error;
2316 }
2317 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2318 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002319 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 goto error;
2321 }
2322 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 /* check mandatory information */
2325 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002326 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 goto error;
2328 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002331
Pavol Vicane994fda2016-03-22 10:47:58 +01002332 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002333
2334error:
2335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002336 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002337}
2338
Michal Vasko0d343d12015-08-24 14:57:36 +02002339/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002341fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2342 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002343{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 struct lyxml_elem *child;
2345 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002348 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2349 /* garbage */
2350 continue;
2351 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002352 if (!strcmp(child->name, "revision-date")) {
2353 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002354 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 goto error;
2356 }
2357 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002358 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 goto error;
2360 }
2361 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2362 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002363 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 goto error;
2365 }
2366 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002369
Pavol Vican0adf01d2016-03-22 12:29:33 +01002370 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002371
2372error:
2373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002375}
2376
Michal Vasko0d343d12015-08-24 14:57:36 +02002377/* logs directly
2378 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002379 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002380 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002381 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002382 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383static int
Radek Krejcib8048692015-08-05 13:36:34 +02002384read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002385 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002386{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 const char *value;
2388 struct lyxml_elem *sub, *next;
2389 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002392 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 if (opt & OPT_IDENT) {
2396 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002397 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 goto error;
2399 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002400 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002402
Radek Krejci6764bb32015-07-03 15:16:04 +02002403 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002404 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002405 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002406 }
2407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408 /* process local parameters */
2409 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002410 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002411 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002412 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002413 continue;
2414 }
2415 if (strcmp(sub->ns->value, LY_NSYIN)) {
2416 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002417 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002418 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002419 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002420 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002421 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002422 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002423 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002424 goto error;
2425 }
2426 }
2427
2428 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002429 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002430 continue;
2431 }
2432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002434 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002435 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 goto error;
2437 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002438 node->dsc = read_yin_subnode(ctx, sub, "text");
2439 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002440 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 }
2442 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002443 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002444 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 goto error;
2446 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002447 node->ref = read_yin_subnode(ctx, sub, "text");
2448 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002449 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 }
2451 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002452 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002453 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002454 goto error;
2455 }
2456 GETVAL(value, sub, "value");
2457 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002458 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002460 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002461 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002462 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002463 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002464 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002465 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 }
2467 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002468 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002469 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 goto error;
2471 }
2472 GETVAL(value, sub, "value");
2473 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002474 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002476 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002478 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002479 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002481 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002483 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 continue;
2485 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002486 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002488
Radek Krejci1d82ef62015-08-07 14:44:40 +02002489 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002490 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002491 if (parent && (parent->flags & LYS_CONFIG_R)) {
2492 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 } else {
2494 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002495 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 }
2497 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002500
2501error:
2502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002504}
2505
Michal Vasko0d343d12015-08-24 14:57:36 +02002506/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002507static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002508read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002509{
Radek Krejci76512572015-08-04 09:47:08 +02002510 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002511 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002512 const char *value;
2513
2514 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002515 if (!retval) {
2516 LOGMEM;
2517 return NULL;
2518 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002519
2520 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002521 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002522 if (!retval->cond) {
2523 goto error;
2524 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002525 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002526 goto error;
2527 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002528
Radek Krejci73adb602015-07-02 18:07:40 +02002529 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002530 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2531 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002532 continue;
2533 }
2534
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002535 if (!strcmp(child->name, "description")) {
2536 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002537 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002538 goto error;
2539 }
2540 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2541 if (!retval->dsc) {
2542 goto error;
2543 }
2544 } else if (!strcmp(child->name, "reference")) {
2545 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002546 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002547 goto error;
2548 }
2549 retval->ref = read_yin_subnode(module->ctx, child, "text");
2550 if (!retval->ref) {
2551 goto error;
2552 }
2553 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002554 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002555 goto error;
2556 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002557 }
2558
2559 return retval;
2560
2561error:
2562
Michal Vasko0308dd62015-10-07 09:14:40 +02002563 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002564 return NULL;
2565}
2566
Michal Vasko0d343d12015-08-24 14:57:36 +02002567/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002568static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002569read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2570 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002571{
Michal Vasko29fc0182015-08-24 15:02:39 +02002572 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002573 struct lys_node_case *cs;
2574 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002575 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002576
Radek Krejcie867c852015-08-27 09:52:34 +02002577 /* init */
2578 memset(&root, 0, sizeof root);
2579
Radek Krejci1d82ef62015-08-07 14:44:40 +02002580 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002581 if (!cs) {
2582 LOGMEM;
2583 return NULL;
2584 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002585 cs->nodetype = LYS_CASE;
2586 cs->prev = (struct lys_node *)cs;
2587 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002588
Radek Krejci6a113852015-07-03 16:04:20 +02002589 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 goto error;
2591 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002592
Radek Krejcia9544502015-08-14 08:24:29 +02002593 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2594
Michal Vasko3a0043f2015-08-12 12:11:30 +02002595 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002596 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002597 goto error;
2598 }
2599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 /* process choice's specific children */
2601 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002602 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2603 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002604 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002605 continue;
2606 }
2607
Michal Vasko29fc0182015-08-24 15:02:39 +02002608 if (!strcmp(sub->name, "container") ||
2609 !strcmp(sub->name, "leaf-list") ||
2610 !strcmp(sub->name, "leaf") ||
2611 !strcmp(sub->name, "list") ||
2612 !strcmp(sub->name, "uses") ||
2613 !strcmp(sub->name, "choice") ||
2614 !strcmp(sub->name, "anyxml")) {
2615
Michal Vaskof3930de2015-10-22 12:03:59 +02002616 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002617 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002618 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002619 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002620 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002621 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002622 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002624 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002625 goto error;
2626 }
2627
Radek Krejci1d82ef62015-08-07 14:44:40 +02002628 cs->when = read_yin_when(module, sub);
2629 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002630 goto error;
2631 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002632
Michal Vasko345da0a2015-12-02 10:35:55 +01002633 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002635 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002637 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002639
Radek Krejci3cf9e222015-06-18 11:37:50 +02002640 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002641 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002642 if (!cs->features) {
2643 LOGMEM;
2644 goto error;
2645 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002646 }
Radek Krejci73adb602015-07-02 18:07:40 +02002647 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002648 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002649 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002650 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002651 goto error;
2652 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002653 }
Radek Krejcib388c152015-06-04 17:03:03 +02002654
Michal Vasko29fc0182015-08-24 15:02:39 +02002655 /* last part - process data nodes */
2656 LY_TREE_FOR_SAFE(root.child, next, sub) {
2657 if (!strcmp(sub->name, "container")) {
2658 node = read_yin_container(module, retval, sub, resolve, unres);
2659 } else if (!strcmp(sub->name, "leaf-list")) {
2660 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2661 } else if (!strcmp(sub->name, "leaf")) {
2662 node = read_yin_leaf(module, retval, sub, resolve, unres);
2663 } else if (!strcmp(sub->name, "list")) {
2664 node = read_yin_list(module, retval, sub, resolve, unres);
2665 } else if (!strcmp(sub->name, "choice")) {
2666 node = read_yin_choice(module, retval, sub, resolve, unres);
2667 } else if (!strcmp(sub->name, "uses")) {
2668 node = read_yin_uses(module, retval, sub, resolve, unres);
2669 } else if (!strcmp(sub->name, "anyxml")) {
2670 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2671 }
2672 if (!node) {
2673 goto error;
2674 }
2675
Michal Vasko345da0a2015-12-02 10:35:55 +01002676 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002677 }
2678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002680
2681error:
2682
Michal Vasko29fc0182015-08-24 15:02:39 +02002683 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002684 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002685 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002686 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002689}
2690
Michal Vasko0d343d12015-08-24 14:57:36 +02002691/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002692static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002693read_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 +02002694{
Radek Krejci629cdef2016-06-06 15:06:36 +02002695 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002696 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002697 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002698 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02002699 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02002700 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002703 if (!choice) {
2704 LOGMEM;
2705 return NULL;
2706 }
Radek Krejci76512572015-08-04 09:47:08 +02002707 choice->nodetype = LYS_CHOICE;
2708 choice->prev = (struct lys_node *)choice;
2709 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002710
Michal Vaskoe0c59842015-09-24 13:52:20 +02002711 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2712 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 goto error;
2714 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002715
Radek Krejcia9544502015-08-14 08:24:29 +02002716 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2717
Michal Vasko3a0043f2015-08-12 12:11:30 +02002718 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002719 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002720 goto error;
2721 }
2722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 /* process choice's specific children */
2724 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002725 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2726 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002727 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002728 continue;
2729 }
2730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002732 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 goto error;
2734 }
2735 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002736 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002737 goto error;
2738 }
2739 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002740 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 goto error;
2742 }
2743 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002744 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 goto error;
2746 }
2747 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 goto error;
2750 }
2751 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002752 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 goto error;
2754 }
2755 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02002756 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002757 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 goto error;
2759 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002760 dflt = sub;
2761 lyxml_unlink_elem(ctx, dflt, 0);
2762
Radek Krejcif9a312c2016-06-06 15:14:30 +02002763 continue;
2764 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
2765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 } else if (!strcmp(sub->name, "mandatory")) {
2767 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002768 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 goto error;
2770 }
2771 /* just checking the flags in leaf is not sufficient, we would allow
2772 * multiple mandatory statements with the "false" value
2773 */
2774 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002776 GETVAL(value, sub, "value");
2777 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002778 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002779 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002780 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002781 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002782 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 goto error;
2784 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002785 } else if (!strcmp(sub->name, "when")) {
2786 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002787 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002788 goto error;
2789 }
2790
2791 choice->when = read_yin_when(module, sub);
2792 if (!choice->when) {
2793 goto error;
2794 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002795 } else if (!strcmp(sub->name, "if-feature")) {
2796 c_ftrs++;
2797
Michal Vasko345da0a2015-12-02 10:35:55 +01002798 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002799 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002801 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002804
Radek Krejci1d82ef62015-08-07 14:44:40 +02002805 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002806 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002808
Radek Krejci3cf9e222015-06-18 11:37:50 +02002809 if (c_ftrs) {
2810 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002811 if (!choice->features) {
2812 LOGMEM;
2813 goto error;
2814 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002815 }
2816
Radek Krejci73adb602015-07-02 18:07:40 +02002817 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002818 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002819 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002820 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002821 goto error;
2822 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002823 }
2824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02002826 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002827 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2828 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002829 goto error;
2830 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02002833 if (dflt) {
2834 GETVAL(value, dflt, "value");
2835 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002836 goto error;
2837 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002838 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002842
2843error:
2844
Radek Krejci629cdef2016-06-06 15:06:36 +02002845 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002846 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002849}
2850
Michal Vasko0d343d12015-08-24 14:57:36 +02002851/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002852static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002853read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002854 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002855{
Radek Krejci76512572015-08-04 09:47:08 +02002856 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002857 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002858 struct lyxml_elem *sub, *next;
2859 const char *value;
2860 int r;
2861 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002862 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002864 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002865 if (!anyxml) {
2866 LOGMEM;
2867 return NULL;
2868 }
Radek Krejci76512572015-08-04 09:47:08 +02002869 anyxml->nodetype = LYS_ANYXML;
2870 anyxml->prev = (struct lys_node *)anyxml;
2871 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002872
Michal Vaskoe0c59842015-09-24 13:52:20 +02002873 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2874 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 goto error;
2876 }
Radek Krejci863c2852015-06-03 15:47:11 +02002877
Radek Krejcia9544502015-08-14 08:24:29 +02002878 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002879
Radek Krejcic4283442016-04-22 09:19:27 +02002880 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002881 goto error;
2882 }
2883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002885 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2886 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002887 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002888 continue;
2889 }
2890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002891 if (!strcmp(sub->name, "mandatory")) {
2892 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002893 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002894 goto error;
2895 }
2896 /* just checking the flags in leaf is not sufficient, we would allow
2897 * multiple mandatory statements with the "false" value
2898 */
2899 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002901 GETVAL(value, sub, "value");
2902 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002903 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002904 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002905 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002906 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002907 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908 goto error;
2909 }
2910 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002911 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002912 } else if (!strcmp(sub->name, "when")) {
2913 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002914 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002915 goto error;
2916 }
2917
2918 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002919 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002920 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002921 goto error;
2922 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002923 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 } else if (!strcmp(sub->name, "must")) {
2925 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002926 } else if (!strcmp(sub->name, "if-feature")) {
2927 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002930 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002932 }
2933 }
Radek Krejci863c2852015-06-03 15:47:11 +02002934
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935 /* middle part - process nodes with cardinality of 0..n */
2936 if (c_must) {
2937 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002938 if (!anyxml->must) {
2939 LOGMEM;
2940 goto error;
2941 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002943 if (c_ftrs) {
2944 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002945 if (!anyxml->features) {
2946 LOGMEM;
2947 goto error;
2948 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002949 }
Radek Krejci863c2852015-06-03 15:47:11 +02002950
Radek Krejci73adb602015-07-02 18:07:40 +02002951 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002953 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2954 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 if (r) {
2956 goto error;
2957 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002958 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002959 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002960 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002961 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002962 goto error;
2963 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002965 }
Radek Krejci863c2852015-06-03 15:47:11 +02002966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002968
2969error:
2970
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002971 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02002972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002974}
2975
Michal Vasko0d343d12015-08-24 14:57:36 +02002976/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002977static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002978read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002979 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002980{
Radek Krejci76512572015-08-04 09:47:08 +02002981 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002982 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 struct lyxml_elem *sub, *next;
2984 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01002985 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002986 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002987
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01002989 if (!leaf) {
2990 LOGMEM;
2991 return NULL;
2992 }
Radek Krejci76512572015-08-04 09:47:08 +02002993 leaf->nodetype = LYS_LEAF;
2994 leaf->prev = (struct lys_node *)leaf;
2995 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002996
Michal Vaskoe0c59842015-09-24 13:52:20 +02002997 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2998 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 goto error;
3000 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003001
Radek Krejcia9544502015-08-14 08:24:29 +02003002 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003003
Radek Krejcic4283442016-04-22 09:19:27 +02003004 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003005 goto error;
3006 }
3007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003009 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3010 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003011 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003012 continue;
3013 }
3014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003015 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003016 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003017 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 goto error;
3019 }
Michal Vasko88c29542015-11-27 14:57:53 +01003020 /* HACK for unres */
3021 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003022 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci48464ed2016-03-17 15:44:09 +01003023 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003024 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 goto error;
3026 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003027 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003028 } else if (!strcmp(sub->name, "default")) {
3029 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003030 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 goto error;
3032 }
3033 GETVAL(value, sub, "value");
3034 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3035 } else if (!strcmp(sub->name, "units")) {
3036 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003037 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 goto error;
3039 }
3040 GETVAL(value, sub, "name");
3041 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3042 } else if (!strcmp(sub->name, "mandatory")) {
3043 if (f_mand) {
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 /* just checking the flags in leaf is not sufficient, we would allow
3048 * multiple mandatory statements with the "false" value
3049 */
3050 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 GETVAL(value, sub, "value");
3053 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003054 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003055 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003056 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003057 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003058 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 goto error;
3060 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003061 } else if (!strcmp(sub->name, "when")) {
3062 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003063 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003064 goto error;
3065 }
3066
3067 leaf->when = read_yin_when(module, sub);
3068 if (!leaf->when) {
3069 goto error;
3070 }
3071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003073 c_must++;
3074 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003075 } else if (!strcmp(sub->name, "if-feature")) {
3076 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003079 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003080 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003082 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003083
Michal Vasko88c29542015-11-27 14:57:53 +01003084 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003088 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003089 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 goto error;
3091 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003092 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003093 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003094 goto error;
3095 }
Radek Krejci841ec082016-04-05 13:05:17 +02003096 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003097 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003098 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003099 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003100 goto error;
3101 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 /* middle part - process nodes with cardinality of 0..n */
3105 if (c_must) {
3106 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003107 if (!leaf->must) {
3108 LOGMEM;
3109 goto error;
3110 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003111 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003112 if (c_ftrs) {
3113 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003114 if (!leaf->features) {
3115 LOGMEM;
3116 goto error;
3117 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003118 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003119
Radek Krejci73adb602015-07-02 18:07:40 +02003120 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003122 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3123 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 if (r) {
3125 goto error;
3126 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003127 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003128 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003129 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003130 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003131 goto error;
3132 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003134 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003137
3138error:
3139
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003140 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003143}
3144
Michal Vasko0d343d12015-08-24 14:57:36 +02003145/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003146static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003147read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003148 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003149{
Radek Krejci76512572015-08-04 09:47:08 +02003150 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003151 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003152 struct lyxml_elem *sub, *next;
3153 const char *value;
3154 char *endptr;
3155 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003156 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003157 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003158 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003161 if (!llist) {
3162 LOGMEM;
3163 return NULL;
3164 }
Radek Krejci76512572015-08-04 09:47:08 +02003165 llist->nodetype = LYS_LEAFLIST;
3166 llist->prev = (struct lys_node *)llist;
3167 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003168
Michal Vaskoe0c59842015-09-24 13:52:20 +02003169 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3170 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 goto error;
3172 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003173
Radek Krejcia9544502015-08-14 08:24:29 +02003174 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003175
Radek Krejcic4283442016-04-22 09:19:27 +02003176 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003177 goto error;
3178 }
3179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003180 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003181 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3182 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003183 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003184 continue;
3185 }
3186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003188 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003189 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 goto error;
3191 }
Michal Vasko88c29542015-11-27 14:57:53 +01003192 /* HACK for unres */
3193 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003194 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci48464ed2016-03-17 15:44:09 +01003195 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003196 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 goto error;
3198 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003199 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 } else if (!strcmp(sub->name, "units")) {
3201 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003202 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 goto error;
3204 }
3205 GETVAL(value, sub, "name");
3206 llist->units = lydict_insert(module->ctx, value, strlen(value));
3207 } else if (!strcmp(sub->name, "ordered-by")) {
3208 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003209 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 goto error;
3211 }
3212 /* just checking the flags in llist is not sufficient, we would
3213 * allow multiple ordered-by statements with the "system" value
3214 */
3215 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003216
Radek Krejci1574a8d2015-08-03 14:16:52 +02003217 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3219 * state data
3220 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003221 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 continue;
3223 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 GETVAL(value, sub, "value");
3226 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003227 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003229 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003231 } /* else system is the default value, so we can ignore it */
3232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 } else if (!strcmp(sub->name, "must")) {
3234 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003235 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003236 } else if (!strcmp(sub->name, "if-feature")) {
3237 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 } else if (!strcmp(sub->name, "min-elements")) {
3241 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003242 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 goto error;
3244 }
3245 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 GETVAL(value, sub, "value");
3248 while (isspace(value[0])) {
3249 value++;
3250 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003252 /* convert it to uint32_t */
3253 errno = 0;
3254 endptr = NULL;
3255 val = strtoul(value, &endptr, 10);
3256 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003257 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 goto error;
3259 }
3260 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003261 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003262 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3263 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003264 goto error;
3265 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003266 } else if (!strcmp(sub->name, "max-elements")) {
3267 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003268 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 goto error;
3270 }
3271 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 GETVAL(value, sub, "value");
3274 while (isspace(value[0])) {
3275 value++;
3276 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003277
Radek Krejci0d7b2472016-02-12 11:11:03 +01003278 if (!strcmp(value, "unbounded")) {
3279 llist->max = 0;
3280 } else {
3281 /* convert it to uint32_t */
3282 errno = 0;
3283 endptr = NULL;
3284 val = strtoul(value, &endptr, 10);
3285 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003286 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003287 goto error;
3288 }
3289 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003290 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003291 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3292 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003293 goto error;
3294 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003295 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003296 } else if (!strcmp(sub->name, "when")) {
3297 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003298 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003299 goto error;
3300 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003301
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003302 llist->when = read_yin_when(module, sub);
3303 if (!llist->when) {
3304 goto error;
3305 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003307 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003310
Michal Vasko88c29542015-11-27 14:57:53 +01003311 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003315 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003316 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 goto error;
3318 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 /* middle part - process nodes with cardinality of 0..n */
3321 if (c_must) {
3322 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003323 if (!llist->must) {
3324 LOGMEM;
3325 goto error;
3326 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003328 if (c_ftrs) {
3329 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003330 if (!llist->features) {
3331 LOGMEM;
3332 goto error;
3333 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003334 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003335
Radek Krejci73adb602015-07-02 18:07:40 +02003336 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003338 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3339 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 if (r) {
3341 goto error;
3342 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003343 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003344 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003345 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003346 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003347 goto error;
3348 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003353
3354error:
3355
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003356 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003359}
3360
Michal Vasko0d343d12015-08-24 14:57:36 +02003361/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003362static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003363read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3364 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003365{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003366 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003367 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003369 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003370 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003372 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 char *auxs;
3374 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 /* init */
3377 memset(&root, 0, sizeof root);
3378 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003381 if (!list) {
3382 LOGMEM;
3383 return NULL;
3384 }
Radek Krejci76512572015-08-04 09:47:08 +02003385 list->nodetype = LYS_LIST;
3386 list->prev = (struct lys_node *)list;
3387 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003388
Michal Vaskoe0c59842015-09-24 13:52:20 +02003389 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3390 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 goto error;
3392 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003393
Radek Krejcia9544502015-08-14 08:24:29 +02003394 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 /* process list's specific children */
3397 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003398 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3399 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003400 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003401 continue;
3402 }
3403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 /* data statements */
3405 if (!strcmp(sub->name, "container") ||
3406 !strcmp(sub->name, "leaf-list") ||
3407 !strcmp(sub->name, "leaf") ||
3408 !strcmp(sub->name, "list") ||
3409 !strcmp(sub->name, "choice") ||
3410 !strcmp(sub->name, "uses") ||
3411 !strcmp(sub->name, "grouping") ||
3412 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003413 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003414 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 /* array counters */
3417 } else if (!strcmp(sub->name, "key")) {
3418 /* check cardinality 0..1 */
3419 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003420 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 goto error;
3422 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003424 /* count the number of keys */
3425 GETVAL(value, sub, "value");
3426 key_str = value;
3427 while ((value = strpbrk(value, " \t\n"))) {
3428 list->keys_size++;
3429 while (isspace(*value)) {
3430 value++;
3431 }
3432 }
3433 list->keys_size++;
3434 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003435 if (!list->keys) {
3436 LOGMEM;
3437 goto error;
3438 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 } else if (!strcmp(sub->name, "unique")) {
3440 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003441 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003442 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 } else if (!strcmp(sub->name, "typedef")) {
3444 c_tpdf++;
3445 } else if (!strcmp(sub->name, "must")) {
3446 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003447 } else if (!strcmp(sub->name, "if-feature")) {
3448 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 /* optional stetments */
3451 } else if (!strcmp(sub->name, "ordered-by")) {
3452 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003453 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 goto error;
3455 }
3456 /* just checking the flags in llist is not sufficient, we would
3457 * allow multiple ordered-by statements with the "system" value
3458 */
3459 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003460
Radek Krejci1574a8d2015-08-03 14:16:52 +02003461 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3463 * state data
3464 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003465 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 continue;
3467 }
Radek Krejci345ad742015-06-03 11:04:18 +02003468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 GETVAL(value, sub, "value");
3470 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003471 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003473 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 goto error;
3475 }
3476 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003477 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 } else if (!strcmp(sub->name, "min-elements")) {
3479 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003480 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 goto error;
3482 }
3483 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 GETVAL(value, sub, "value");
3486 while (isspace(value[0])) {
3487 value++;
3488 }
Radek Krejci345ad742015-06-03 11:04:18 +02003489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 /* convert it to uint32_t */
3491 errno = 0;
3492 auxs = NULL;
3493 val = strtoul(value, &auxs, 10);
3494 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003495 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 goto error;
3497 }
3498 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003499 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003500 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3501 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003502 lyxml_free(module->ctx, sub);
3503 goto error;
3504 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003505 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 } else if (!strcmp(sub->name, "max-elements")) {
3507 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003508 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 goto error;
3510 }
3511 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 GETVAL(value, sub, "value");
3514 while (isspace(value[0])) {
3515 value++;
3516 }
Radek Krejci345ad742015-06-03 11:04:18 +02003517
Radek Krejci0d7b2472016-02-12 11:11:03 +01003518 if (!strcmp(value, "unbounded")) {
3519 list->max = 0;;
3520 } else {
3521 /* convert it to uint32_t */
3522 errno = 0;
3523 auxs = NULL;
3524 val = strtoul(value, &auxs, 10);
3525 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003526 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003527 goto error;
3528 }
3529 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003530 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003531 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3532 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003533 goto error;
3534 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003536 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003537 } else if (!strcmp(sub->name, "when")) {
3538 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003539 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003540 goto error;
3541 }
3542
3543 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003544 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003545 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003546 goto error;
3547 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003548 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003549 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003550 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003551 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 }
3553 }
Radek Krejci345ad742015-06-03 11:04:18 +02003554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003556 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003557 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 goto error;
3559 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3562 if (c_tpdf) {
3563 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003564 if (!list->tpdf) {
3565 LOGMEM;
3566 goto error;
3567 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003569 if (c_must) {
3570 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003571 if (!list->must) {
3572 LOGMEM;
3573 goto error;
3574 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003575 }
3576 if (c_ftrs) {
3577 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003578 if (!list->features) {
3579 LOGMEM;
3580 goto error;
3581 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003582 }
Radek Krejci73adb602015-07-02 18:07:40 +02003583 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003585 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3586 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 if (r) {
3588 goto error;
3589 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003590 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003591 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003592 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003593 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003594 goto error;
3595 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003596 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003597 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3598 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003599 if (r) {
3600 goto error;
3601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 }
3603 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003604
Radek Krejcic4283442016-04-22 09:19:27 +02003605 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003606 goto error;
3607 }
3608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 /* last part - process data nodes */
3610 LY_TREE_FOR_SAFE(root.child, next, sub) {
3611 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003612 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003614 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003616 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003617 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003618 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003620 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003622 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003624 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003626 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003627 } else {
3628 LOGINT;
3629 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003630 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003631 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 goto error;
3633 }
Radek Krejci73adb602015-07-02 18:07:40 +02003634
Michal Vasko345da0a2015-12-02 10:35:55 +01003635 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003637
Radek Krejci461efb92016-02-12 15:52:18 +01003638 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003639 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003640 goto error;
3641 }
3642 } /* 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 +02003643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003644 /* process unique statements */
3645 if (c_uniq) {
3646 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003647 if (!list->unique) {
3648 LOGMEM;
3649 goto error;
3650 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003651
Radek Krejci461efb92016-02-12 15:52:18 +01003652 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3653 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3654 list->unique_size++;
3655 if (r) {
3656 goto error;
3657 }
3658
3659 lyxml_free(module->ctx, sub);
3660 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003661 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003664
3665error:
3666
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003667 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003669 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003670 }
3671 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003672 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003673 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003676}
3677
Michal Vasko0d343d12015-08-24 14:57:36 +02003678/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003679static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003680read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3681 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003682{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003684 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003685 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003686 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 const char *value;
3688 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 /* init */
3692 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003695 if (!cont) {
3696 LOGMEM;
3697 return NULL;
3698 }
Radek Krejci76512572015-08-04 09:47:08 +02003699 cont->nodetype = LYS_CONTAINER;
3700 cont->prev = (struct lys_node *)cont;
3701 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003702
Michal Vaskoe0c59842015-09-24 13:52:20 +02003703 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3704 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 goto error;
3706 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003707
Radek Krejcia9544502015-08-14 08:24:29 +02003708 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 /* process container's specific children */
3711 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003712 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003713 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003714 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003715 continue;
3716 }
3717
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 if (!strcmp(sub->name, "presence")) {
3719 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003720 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 goto error;
3722 }
3723 GETVAL(value, sub, "value");
3724 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003725
Michal Vasko345da0a2015-12-02 10:35:55 +01003726 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003727 } else if (!strcmp(sub->name, "when")) {
3728 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003729 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003730 goto error;
3731 }
3732
3733 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003734 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003735 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003736 goto error;
3737 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003738 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 /* data statements */
3741 } else if (!strcmp(sub->name, "container") ||
3742 !strcmp(sub->name, "leaf-list") ||
3743 !strcmp(sub->name, "leaf") ||
3744 !strcmp(sub->name, "list") ||
3745 !strcmp(sub->name, "choice") ||
3746 !strcmp(sub->name, "uses") ||
3747 !strcmp(sub->name, "grouping") ||
3748 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003749 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003750 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 /* array counters */
3753 } else if (!strcmp(sub->name, "typedef")) {
3754 c_tpdf++;
3755 } else if (!strcmp(sub->name, "must")) {
3756 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003757 } else if (!strcmp(sub->name, "if-feature")) {
3758 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003760 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 }
3763 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3766 if (c_tpdf) {
3767 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003768 if (!cont->tpdf) {
3769 LOGMEM;
3770 goto error;
3771 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 }
3773 if (c_must) {
3774 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003775 if (!cont->must) {
3776 LOGMEM;
3777 goto error;
3778 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003779 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003780 if (c_ftrs) {
3781 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003782 if (!cont->features) {
3783 LOGMEM;
3784 goto error;
3785 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003786 }
Radek Krejci800af702015-06-02 13:46:01 +02003787
Radek Krejci73adb602015-07-02 18:07:40 +02003788 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003790 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3791 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 if (r) {
3793 goto error;
3794 }
3795 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003796 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3797 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 if (r) {
3799 goto error;
3800 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003801 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003802 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003803 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003804 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003805 goto error;
3806 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003809
Radek Krejcic4283442016-04-22 09:19:27 +02003810 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003811 goto error;
3812 }
3813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 /* last part - process data nodes */
3815 LY_TREE_FOR_SAFE(root.child, next, sub) {
3816 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003817 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003819 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003821 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003823 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003825 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003827 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003829 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003831 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003833 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 goto error;
3835 }
Radek Krejci73adb602015-07-02 18:07:40 +02003836
Michal Vasko345da0a2015-12-02 10:35:55 +01003837 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003841
3842error:
3843
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003844 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003846 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003850}
3851
Michal Vasko0d343d12015-08-24 14:57:36 +02003852/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003853static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003855 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003856{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003858 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003859 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003860 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 int r;
3862 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003864 /* init */
3865 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003867 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003868 if (!grp) {
3869 LOGMEM;
3870 return NULL;
3871 }
Radek Krejci76512572015-08-04 09:47:08 +02003872 grp->nodetype = LYS_GROUPING;
3873 grp->prev = (struct lys_node *)grp;
3874 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003875
Michal Vasko71e1aa82015-08-12 12:17:51 +02003876 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 goto error;
3878 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003879
Radek Krejcia9544502015-08-14 08:24:29 +02003880 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3881
Radek Krejci1d82ef62015-08-07 14:44:40 +02003882 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003883 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3884 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003885 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003886 continue;
3887 }
3888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 /* data statements */
3890 if (!strcmp(sub->name, "container") ||
3891 !strcmp(sub->name, "leaf-list") ||
3892 !strcmp(sub->name, "leaf") ||
3893 !strcmp(sub->name, "list") ||
3894 !strcmp(sub->name, "choice") ||
3895 !strcmp(sub->name, "uses") ||
3896 !strcmp(sub->name, "grouping") ||
3897 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003898 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003899 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 /* array counters */
3902 } else if (!strcmp(sub->name, "typedef")) {
3903 c_tpdf++;
3904 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003905 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003906 goto error;
3907 }
3908 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003910 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3911 if (c_tpdf) {
3912 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003913 if (!grp->tpdf) {
3914 LOGMEM;
3915 goto error;
3916 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003918 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003919 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3920 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003921 if (r) {
3922 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003923 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003925
Radek Krejcic4283442016-04-22 09:19:27 +02003926 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003927 goto error;
3928 }
3929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02003931 if (!root.child) {
3932 LOGWRN("Grouping \"%s\" without children.", retval->name);
3933 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 LY_TREE_FOR_SAFE(root.child, next, sub) {
3935 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003936 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003937 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003938 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003939 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003940 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003941 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003942 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003944 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003946 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003948 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003950 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 goto error;
3954 }
Radek Krejci73adb602015-07-02 18:07:40 +02003955
Michal Vasko345da0a2015-12-02 10:35:55 +01003956 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
3961error:
3962
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003963 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003965 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969}
3970
Michal Vasko0d343d12015-08-24 14:57:36 +02003971/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003972static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003973read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3974 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003975{
Radek Krejcie0674f82015-06-15 13:58:51 +02003976 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003977 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003978 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003979 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003980 int r;
3981 int c_tpdf = 0;
3982
Radek Krejcie0674f82015-06-15 13:58:51 +02003983 /* init */
3984 memset(&root, 0, sizeof root);
3985
Michal Vasko38d01f72015-06-15 09:41:06 +02003986 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01003987 if (!inout) {
3988 LOGMEM;
3989 return NULL;
3990 }
Radek Krejci6acc8012015-08-13 09:07:04 +02003991 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003992
3993 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003994 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02003995 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02003996 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003997 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02003998 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02003999 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004000 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004001 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004002 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004003 }
4004
Radek Krejci76512572015-08-04 09:47:08 +02004005 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004006
Radek Krejci6a113852015-07-03 16:04:20 +02004007 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004008 goto error;
4009 }
4010
Radek Krejcia9544502015-08-14 08:24:29 +02004011 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4012
Michal Vasko38d01f72015-06-15 09:41:06 +02004013 /* data statements */
4014 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004015 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4016 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004017 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004018 continue;
4019 }
4020
Michal Vasko38d01f72015-06-15 09:41:06 +02004021 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004022 !strcmp(sub->name, "leaf-list") ||
4023 !strcmp(sub->name, "leaf") ||
4024 !strcmp(sub->name, "list") ||
4025 !strcmp(sub->name, "choice") ||
4026 !strcmp(sub->name, "uses") ||
4027 !strcmp(sub->name, "grouping") ||
4028 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004029 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004030 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004032 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004033 } else if (!strcmp(sub->name, "typedef")) {
4034 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004035
Michal Vasko38d01f72015-06-15 09:41:06 +02004036 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004037 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004038 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004039 }
4040 }
4041
4042 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4043 if (c_tpdf) {
4044 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004045 if (!inout->tpdf) {
4046 LOGMEM;
4047 goto error;
4048 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004049 }
4050
Radek Krejci73adb602015-07-02 18:07:40 +02004051 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004052 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4053 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004054 if (r) {
4055 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004056 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004057 }
4058
Radek Krejcic4283442016-04-22 09:19:27 +02004059 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004060 goto error;
4061 }
4062
Michal Vasko38d01f72015-06-15 09:41:06 +02004063 /* last part - process data nodes */
4064 LY_TREE_FOR_SAFE(root.child, next, sub) {
4065 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004066 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004067 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004068 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004069 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004070 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004071 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004072 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004073 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004074 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004075 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004076 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004077 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004078 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004079 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004081 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004083 goto error;
4084 }
Radek Krejci73adb602015-07-02 18:07:40 +02004085
Michal Vasko345da0a2015-12-02 10:35:55 +01004086 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004087 }
4088
Michal Vasko38d01f72015-06-15 09:41:06 +02004089 return retval;
4090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004092
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004093 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004094 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004095 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004096 }
4097
4098 return NULL;
4099}
4100
Michal Vasko0d343d12015-08-24 14:57:36 +02004101/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004102static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004103read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4104 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004105{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004106 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004107 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004108 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004109 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004110 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004111 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004112
Michal Vaskoc6551b32015-06-16 10:51:43 +02004113 memset(&root, 0, sizeof root);
4114
Michal Vasko0ea41032015-06-16 08:53:55 +02004115 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004116 if (!notif) {
4117 LOGMEM;
4118 return NULL;
4119 }
Radek Krejci76512572015-08-04 09:47:08 +02004120 notif->nodetype = LYS_NOTIF;
4121 notif->prev = (struct lys_node *)notif;
4122 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004123
Radek Krejci6a113852015-07-03 16:04:20 +02004124 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004125 goto error;
4126 }
4127
Radek Krejcia9544502015-08-14 08:24:29 +02004128 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4129
Michal Vasko0ea41032015-06-16 08:53:55 +02004130 /* process rpc's specific children */
4131 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004132 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4133 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004134 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004135 continue;
4136 }
4137
Michal Vasko0ea41032015-06-16 08:53:55 +02004138 /* data statements */
4139 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004140 !strcmp(sub->name, "leaf-list") ||
4141 !strcmp(sub->name, "leaf") ||
4142 !strcmp(sub->name, "list") ||
4143 !strcmp(sub->name, "choice") ||
4144 !strcmp(sub->name, "uses") ||
4145 !strcmp(sub->name, "grouping") ||
4146 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004147 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004148 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004150 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004151 } else if (!strcmp(sub->name, "typedef")) {
4152 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004153 } else if (!strcmp(sub->name, "if-feature")) {
4154 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004155 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004156 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004157 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004158 }
4159 }
4160
4161 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4162 if (c_tpdf) {
4163 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004164 if (!notif->tpdf) {
4165 LOGMEM;
4166 goto error;
4167 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004168 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004169 if (c_ftrs) {
4170 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004171 if (!notif->features) {
4172 LOGMEM;
4173 goto error;
4174 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004175 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004176
Radek Krejci73adb602015-07-02 18:07:40 +02004177 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004178 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004179 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4180 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004181 if (r) {
4182 goto error;
4183 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004184 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004185 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004186 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004187 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004188 goto error;
4189 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004190 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004191 }
4192
Radek Krejcic4283442016-04-22 09:19:27 +02004193 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004194 goto error;
4195 }
4196
Michal Vasko0ea41032015-06-16 08:53:55 +02004197 /* last part - process data nodes */
4198 LY_TREE_FOR_SAFE(root.child, next, sub) {
4199 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004200 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004201 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004202 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004203 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004204 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004205 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004206 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004207 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004208 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004209 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004210 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004211 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004212 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004213 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004215 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004216 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004217 goto error;
4218 }
Radek Krejci73adb602015-07-02 18:07:40 +02004219
Michal Vasko345da0a2015-12-02 10:35:55 +01004220 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004221 }
4222
Michal Vasko0ea41032015-06-16 08:53:55 +02004223 return retval;
4224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004225error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004226
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004227 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004228 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004229 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004230 }
4231
4232 return NULL;
4233}
4234
Michal Vasko0d343d12015-08-24 14:57:36 +02004235/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004236static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004237read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4238 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004239{
Radek Krejcie0674f82015-06-15 13:58:51 +02004240 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004241 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004242 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004243 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004244 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004245 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004246
Radek Krejcie0674f82015-06-15 13:58:51 +02004247 /* init */
4248 memset(&root, 0, sizeof root);
4249
Michal Vasko38d01f72015-06-15 09:41:06 +02004250 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004251 if (!rpc) {
4252 LOGMEM;
4253 return NULL;
4254 }
Radek Krejci76512572015-08-04 09:47:08 +02004255 rpc->nodetype = LYS_RPC;
4256 rpc->prev = (struct lys_node *)rpc;
4257 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004258
Radek Krejci6a113852015-07-03 16:04:20 +02004259 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004260 goto error;
4261 }
4262
Radek Krejcia9544502015-08-14 08:24:29 +02004263 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4264
Michal Vasko38d01f72015-06-15 09:41:06 +02004265 /* process rpc's specific children */
4266 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004267 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4268 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004269 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004270 continue;
4271 }
4272
Michal Vasko38d01f72015-06-15 09:41:06 +02004273 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004274 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004275 && (rpc->child->nodetype == LYS_INPUT
4276 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004277 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004278 goto error;
4279 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004280 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004281 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004282 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004284 && (rpc->child->nodetype == LYS_INPUT
4285 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004286 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004287 goto error;
4288 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004289 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004290 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004292 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004293 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004294 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004295 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004297 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004298 } else if (!strcmp(sub->name, "typedef")) {
4299 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004300 } else if (!strcmp(sub->name, "if-feature")) {
4301 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004302 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004303 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004304 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004305 }
4306 }
4307
4308 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4309 if (c_tpdf) {
4310 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004311 if (!rpc->tpdf) {
4312 LOGMEM;
4313 goto error;
4314 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004315 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004316 if (c_ftrs) {
4317 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004318 if (!rpc->features) {
4319 LOGMEM;
4320 goto error;
4321 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004322 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004323
Radek Krejci73adb602015-07-02 18:07:40 +02004324 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004325 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004326 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4327 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004328 if (r) {
4329 goto error;
4330 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004331 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004332 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004333 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004334 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004335 goto error;
4336 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004337 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004338 }
4339
Radek Krejcic4283442016-04-22 09:19:27 +02004340 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004341 goto error;
4342 }
4343
Michal Vasko38d01f72015-06-15 09:41:06 +02004344 /* last part - process data nodes */
4345 LY_TREE_FOR_SAFE(root.child, next, sub) {
4346 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004347 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004348 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004349 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004350 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004351 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004352 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004353 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004354 goto error;
4355 }
Radek Krejci73adb602015-07-02 18:07:40 +02004356
Michal Vasko345da0a2015-12-02 10:35:55 +01004357 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004358 }
4359
Michal Vasko38d01f72015-06-15 09:41:06 +02004360 return retval;
4361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004363
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004364 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004365 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004366 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004367 }
4368
4369 return NULL;
4370}
4371
Michal Vasko0d343d12015-08-24 14:57:36 +02004372/* logs directly
4373 *
Radek Krejci74705112015-06-05 10:25:44 +02004374 * resolve - referenced grouping should be bounded to the namespace (resolved)
4375 * only when uses does not appear in grouping. In a case of grouping's uses,
4376 * we just get information but we do not apply augment or refine to it.
4377 */
Radek Krejci76512572015-08-04 09:47:08 +02004378static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004379read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004380 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004381{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004383 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004384 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004386 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004387 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004389 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004390 if (!uses) {
4391 LOGMEM;
4392 return NULL;
4393 }
Radek Krejci76512572015-08-04 09:47:08 +02004394 uses->nodetype = LYS_USES;
4395 uses->prev = (struct lys_node *)uses;
4396 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004397
Radek Krejcia9544502015-08-14 08:24:29 +02004398 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004400
Michal Vaskoe0c59842015-09-24 13:52:20 +02004401 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4402 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 goto error;
4404 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004405
Radek Krejcia9544502015-08-14 08:24:29 +02004406 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004409 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004410 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4411 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004412 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004413 continue;
4414 }
4415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 if (!strcmp(sub->name, "refine")) {
4417 c_ref++;
4418 } else if (!strcmp(sub->name, "augment")) {
4419 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004420 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004421 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004422 } else if (!strcmp(sub->name, "when")) {
4423 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004424 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004425 goto error;
4426 }
4427
4428 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004429 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004430 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004431 goto error;
4432 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004433 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004434 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004435 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004437 }
4438 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 /* process properties with cardinality 0..n */
4441 if (c_ref) {
4442 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004443 if (!uses->refine) {
4444 LOGMEM;
4445 goto error;
4446 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 }
4448 if (c_aug) {
4449 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004450 if (!uses->augment) {
4451 LOGMEM;
4452 goto error;
4453 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004455 if (c_ftrs) {
4456 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004457 if (!uses->features) {
4458 LOGMEM;
4459 goto error;
4460 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004461 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004462
Radek Krejcic4283442016-04-22 09:19:27 +02004463 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004464 goto error;
4465 }
4466
Radek Krejcia9544502015-08-14 08:24:29 +02004467 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004469 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4470 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004471 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004472 goto error;
4473 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004474 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004475 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4476 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004477 if (r) {
4478 goto error;
4479 }
4480 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004481 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004482 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004483 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004484 goto error;
4485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486 }
4487 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004488
Radek Krejci48464ed2016-03-17 15:44:09 +01004489 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004490 goto error;
4491 }
Radek Krejci74705112015-06-05 10:25:44 +02004492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 if (resolve) {
4494 /* inherit config flag */
4495 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004496 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 } else {
4498 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004499 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 }
4501 }
Radek Krejcib388c152015-06-04 17:03:03 +02004502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004504
4505error:
4506
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004507 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004510}
4511
Michal Vasko0d343d12015-08-24 14:57:36 +02004512/* logs directly
4513 *
4514 * common code for yin_read_module() and yin_read_submodule()
4515 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516static int
Radek Krejcic071c542016-01-27 14:57:51 +01004517read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4518 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004519{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004521 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004522 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004523 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004524 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004526 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01004527 int inc_size_aux = 0;
4528 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004529 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004530 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 +02004531
Radek Krejcic071c542016-01-27 14:57:51 +01004532 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004533 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 /* init */
4536 memset(&root, 0, sizeof root);
4537 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004538 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 /*
4541 * in the first run, we process elements with cardinality of 1 or 0..1 and
4542 * count elements with cardinality 0..n. Data elements (choices, containers,
4543 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4544 * need have all top-level and groupings already prepared at that time. In
4545 * the middle loop, we process other elements with carinality of 0..n since
4546 * we need to allocate arrays to store them.
4547 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004548 LY_TREE_FOR_SAFE(yin->child, next, child) {
4549 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004550 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004551 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004552 continue;
4553 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004554
Radek Krejcic071c542016-01-27 14:57:51 +01004555 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004557 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 goto error;
4559 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004560 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004562 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004563 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 goto error;
4567 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004568 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004569 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 goto error;
4571 }
4572 module->prefix = 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, "belongs-to")) {
4575 if (submodule->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, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004580 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004581 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 goto error;
4583 }
Radek Krejcif3886932015-06-04 17:36:06 +02004584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004586 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004587 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004589 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004590 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004592 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004593 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 goto error;
4595 }
4596 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004597 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 /* check here differs from a generic prefix check, since this prefix
4599 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004600 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004601 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 goto error;
4603 }
Radek Krejcic071c542016-01-27 14:57:51 +01004604 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004607 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004608
4609 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004610 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004611 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004612 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004614 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004616 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004618 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004620 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004621 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004622 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004623 lyxml_unlink_elem(ctx, child, 2);
4624 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004625
Radek Krejci1d82ef62015-08-07 14:44:40 +02004626 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004627 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004628 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004629 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004632 } else if (!strcmp(child->name, "container") ||
4633 !strcmp(child->name, "leaf-list") ||
4634 !strcmp(child->name, "leaf") ||
4635 !strcmp(child->name, "list") ||
4636 !strcmp(child->name, "choice") ||
4637 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004638 !strcmp(child->name, "anyxml") ||
4639 !strcmp(child->name, "rpc") ||
4640 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004641 lyxml_unlink_elem(ctx, child, 2);
4642 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004643
Radek Krejci1d82ef62015-08-07 14:44:40 +02004644 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004646 lyxml_unlink_elem(ctx, child, 2);
4647 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004650 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004651 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 goto error;
4654 }
Radek Krejcic071c542016-01-27 14:57:51 +01004655 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004656 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004657 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 goto error;
4659 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004660 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004661 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004662 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 goto error;
4664 }
Radek Krejcic071c542016-01-27 14:57:51 +01004665 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004666 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004667 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 goto error;
4669 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004670 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004671 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004672 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 goto error;
4674 }
Radek Krejcic071c542016-01-27 14:57:51 +01004675 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004676 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004677 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 goto error;
4679 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004681 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004682 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 goto error;
4684 }
Radek Krejcic071c542016-01-27 14:57:51 +01004685 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004686 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004687 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 goto error;
4689 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004692 if (version_flag) {
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 Krejci1d82ef62015-08-07 14:44:40 +02004696 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 if (strcmp(value, "1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004698 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 goto error;
4700 }
Radek Krejcic071c542016-01-27 14:57:51 +01004701 version_flag = 1;
4702 if (!submodule) {
4703 module->version = 1;
4704 } /* 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 +01004705 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004706
Radek Krejci1d82ef62015-08-07 14:44:40 +02004707 } else if (!strcmp(child->name, "extension")) {
4708 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004709
Radek Krejci3d468122015-10-02 13:36:12 +02004710 /* we have the following supported (hardcoded) extensions: */
4711 /* ietf-netconf's get-filter-element-attributes */
4712 if (!strcmp(module->ns, LY_NSNC) &&
4713 !strcmp(value, "get-filter-element-attributes")) {
4714 LOGDBG("NETCONF filter extension found");
4715 /* NACM's default-deny-write and default-deny-all */
4716 } else if (!strcmp(module->ns, LY_NSNACM) &&
4717 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4718 LOGDBG("NACM extension found");
4719 /* other extensions are not supported, so inform about such an extension */
4720 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004721 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004722 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004723 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004725 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 }
4728 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004729
Radek Krejcic071c542016-01-27 14:57:51 +01004730 /* check for mandatory statements */
4731 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004732 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004733 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004734 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004736 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 goto error;
4738 }
4739 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004740 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 goto error;
4742 }
4743 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 /* allocate arrays for elements with cardinality of 0..n */
4746 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004747 trg->imp = calloc(c_imp, sizeof *trg->imp);
4748 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004749 LOGMEM;
4750 goto error;
4751 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 }
4753 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004754 trg->rev = calloc(c_rev, sizeof *trg->rev);
4755 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004756 LOGMEM;
4757 goto error;
4758 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004759 }
4760 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004761 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4762 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004763 LOGMEM;
4764 goto error;
4765 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 }
4767 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004768 trg->ident = calloc(c_ident, sizeof *trg->ident);
4769 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004770 LOGMEM;
4771 goto error;
4772 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004773 }
4774 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004775 trg->inc = calloc(c_inc, sizeof *trg->inc);
4776 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004777 LOGMEM;
4778 goto error;
4779 }
Radek Krejcic071c542016-01-27 14:57:51 +01004780 trg->inc_size = c_inc;
4781 /* trg->inc_size can be updated by the included submodules,
4782 * so we will use inc_size_aux here, trg->inc_size stores the
4783 * target size of the array
4784 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004785 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004786 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004787 trg->augment = calloc(c_aug, sizeof *trg->augment);
4788 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004789 LOGMEM;
4790 goto error;
4791 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004792 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004793 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004794 trg->features = calloc(c_ftrs, sizeof *trg->features);
4795 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004796 LOGMEM;
4797 goto error;
4798 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004799 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004800 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004801 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4802 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004803 LOGMEM;
4804 goto error;
4805 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004806 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004807
Michal Vasko2f7925f2015-10-21 15:06:56 +02004808 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4809 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004810 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004811 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4812 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 if (r) {
4814 goto error;
4815 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004818 for (i = 0; i < trg->imp_size - 1; i++) {
4819 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004820 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->imp[i].module->name, "import");
4821 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 goto error;
4823 }
4824 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004825
Radek Krejci1d82ef62015-08-07 14:44:40 +02004826 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004827 memset(&inc, 0, sizeof inc);
4828 /* 1) pass module, not trg, since we want to pass the main module
4829 * 2) we cannot pass directly the structure in the array since
4830 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004831 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004832 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4833 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004834 if (r) {
4835 goto error;
4836 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004839 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004840 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004841 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
4842 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01004843 trg->inc[inc_size_aux - 1].submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 goto error;
4845 }
4846 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004847
Radek Krejci1d82ef62015-08-07 14:44:40 +02004848 } else if (!strcmp(child->name, "revision")) {
4849 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004850 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 goto error;
4852 }
Radek Krejcic071c542016-01-27 14:57:51 +01004853 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004855 for (i = 0; i < trg->rev_size; i++) {
4856 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004857 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4858 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 }
4860 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004861
Radek Krejci1d82ef62015-08-07 14:44:40 +02004862 LY_TREE_FOR(child->child, child2) {
4863 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004864 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004865 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 goto error;
4867 }
Radek Krejcic071c542016-01-27 14:57:51 +01004868 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4869 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 goto error;
4871 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004872 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004873 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004874 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 goto error;
4876 }
Radek Krejcic071c542016-01-27 14:57:51 +01004877 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4878 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 goto error;
4880 }
4881 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004882 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 goto error;
4884 }
4885 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004888 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004890 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004891 if (!value) {
4892 LOGMEM;
4893 goto error;
4894 }
Radek Krejcic071c542016-01-27 14:57:51 +01004895 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4896 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004898
Radek Krejci749190d2016-02-18 16:26:25 +01004899 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004900 value = trg->rev[0].dsc;
4901 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4902 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004904
Radek Krejci749190d2016-02-18 16:26:25 +01004905 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004906 value = trg->rev[0].ref;
4907 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4908 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 }
4910 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004911
Radek Krejcic071c542016-01-27 14:57:51 +01004912 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004913
Radek Krejci1d82ef62015-08-07 14:44:40 +02004914 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004915 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4916 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 if (r) {
4918 goto error;
4919 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004920
Radek Krejci1d82ef62015-08-07 14:44:40 +02004921 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004922 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4923 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 if (r) {
4925 goto error;
4926 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004927
Radek Krejci1d82ef62015-08-07 14:44:40 +02004928 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004929 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4930 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004931 if (r) {
4932 goto error;
4933 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004934
Radek Krejci1d82ef62015-08-07 14:44:40 +02004935 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004936 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4937 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004938 if (r) {
4939 goto error;
4940 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004941 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4942 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004944 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004946
Pavol Vicane994fda2016-03-22 10:47:58 +01004947 if (submodule && lyp_propagate_submodule(module, submodule)) {
Pavol Vicanaa1eba92016-03-09 12:27:11 +01004948 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004949 }
4950
Radek Krejcif5be10f2015-06-16 13:29:36 +02004951 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004952 * refer to them. Submodule's data nodes are stored in the
4953 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004954 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004955 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004956 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004957 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004958 goto error;
4959 }
Radek Krejci74705112015-06-05 10:25:44 +02004960
Michal Vasko345da0a2015-12-02 10:35:55 +01004961 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004962 }
Radek Krejci74705112015-06-05 10:25:44 +02004963
Radek Krejcif5be10f2015-06-16 13:29:36 +02004964 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004965 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004966
Radek Krejci1d82ef62015-08-07 14:44:40 +02004967 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004968 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004969 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004970 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004971 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004972 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004973 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004974 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004975 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004976 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004977 } else if (!strcmp(child->name, "uses")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004978 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004979 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004980 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004981 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004982 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004983 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004984 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004986 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 goto error;
4988 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004989
Michal Vasko345da0a2015-12-02 10:35:55 +01004990 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004992
Michal Vasko2f7925f2015-10-21 15:06:56 +02004993 /* ... and finally augments (last, so we can augment our data, for instance) */
4994 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004995 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
4996 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004997
Michal Vasko2f7925f2015-10-21 15:06:56 +02004998 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004999 goto error;
5000 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005001 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005002 }
5003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005005
5006error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 /* cleanup */
5008 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005009 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 }
5011 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005012 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005014 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005015 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005016 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005019}
5020
Michal Vasko0d343d12015-08-24 14:57:36 +02005021/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005022struct lys_submodule *
5023yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005024{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005025 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005026 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005028
Michal Vasko5a721fd2016-02-16 12:16:48 +01005029 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005030
Radek Krejci722b0072016-02-01 17:09:45 +01005031 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005033 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005034 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005036 /* check root element */
5037 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005038 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 goto error;
5040 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005042 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005043 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 goto error;
5045 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005046
Michal Vasko5a721fd2016-02-16 12:16:48 +01005047 submodule = calloc(1, sizeof *submodule);
5048 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 LOGMEM;
5050 goto error;
5051 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005052
Michal Vasko5a721fd2016-02-16 12:16:48 +01005053 submodule->ctx = module->ctx;
5054 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5055 submodule->type = 1;
5056 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005057
Michal Vasko5a721fd2016-02-16 12:16:48 +01005058 LOGVRB("Reading submodule \"%s\".", submodule->name);
5059 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005060 goto error;
5061 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005063 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005064 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005065
Michal Vasko5a721fd2016-02-16 12:16:48 +01005066 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005067 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005068
5069error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005070 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005071 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005072 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005073
Michal Vasko5a721fd2016-02-16 12:16:48 +01005074 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005075 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005076 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005077 }
5078
Michal Vasko5a721fd2016-02-16 12:16:48 +01005079 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005080
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005081 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5082 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005083 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005084 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005085}
5086
Michal Vasko0d343d12015-08-24 14:57:36 +02005087/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005088struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005089yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005090{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005091 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005092 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005093 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005094 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005095 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005096
Radek Krejcic071c542016-01-27 14:57:51 +01005097 unres = calloc(1, sizeof *unres);
5098 if (!unres) {
5099 LOGMEM;
5100 return NULL;
5101 }
5102
Radek Krejci722b0072016-02-01 17:09:45 +01005103 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005104 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005105 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005108 /* check root element */
5109 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005110 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005111 goto error;
5112 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005115 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 goto error;
5117 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005119 module = calloc(1, sizeof *module);
5120 if (!module) {
5121 LOGMEM;
5122 goto error;
5123 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005125 module->ctx = ctx;
5126 module->name = lydict_insert(ctx, value, strlen(value));
5127 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005128 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005129
Michal Vasko9f258e42016-02-11 11:36:27 +01005130 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005131 if (read_sub_module(module, NULL, yin, unres)) {
5132 goto error;
5133 }
5134
5135 /* resolve rest of unres items */
5136 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 goto error;
5138 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005139
Radek Krejciff4874d2016-03-07 12:30:50 +01005140 if (revision) {
5141 /* check revision of the parsed model */
5142 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005143 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5144 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005145 goto error;
5146 }
5147 }
5148
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005149 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005150 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005152
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005153 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005154 if (!module->implemented) {
5155 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5156 }
Michal Vasko26055752016-05-03 11:36:31 +02005157 if (lys_module_set_implement(module)) {
5158 goto error;
5159 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005160
Michal Vasko26055752016-05-03 11:36:31 +02005161 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5162 goto error;
5163 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005164 for (i = 0; i < module->inc_size; ++i) {
Michal Vasko26055752016-05-03 11:36:31 +02005165 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5166 goto error;
5167 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005168 }
5169 }
5170
Michal Vasko345da0a2015-12-02 10:35:55 +01005171 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005172 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005173 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005174 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005175
5176error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005178 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005179 unres_schema_free(module, &unres);
5180
5181 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005182 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005183 return NULL;
5184 }
5185
5186 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005187
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005188 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005189 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005191}