blob: 19733fadc4a04d11786f34d43e1634080040d8d2 [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 Vaskoe4e8fbd2015-08-24 14:54:49 +0200235 pcre *precomp;
236 int i, j, rc, err_offset;
Radek Krejcidc008d72016-02-17 13:12:14 +0100237 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200238 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200239 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200240
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200241 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100242 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200243 if (!value) {
244 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200245 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200246
247 i = parse_identifier(value);
248 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100249 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100250 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200251 goto error;
252 }
253 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100254 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200255 if (value[i]) {
256 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100257 name += i;
258 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100259 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100260 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200261 goto error;
262 }
Radek Krejci225376f2016-02-16 17:36:22 +0100263 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200264 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200265
Radek Krejci225376f2016-02-16 17:36:22 +0100266 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100267 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200268 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100269 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200270 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100271
272 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200273 } else if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100274 ret = EXIT_FAILURE;
275 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200276 }
277 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200278
Radek Krejcicf509982015-12-15 09:22:44 +0100279 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100280 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100281 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100282 return -1;
283 }
284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200285 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200286 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200287 /* RFC 6020 9.7.4 - bit */
288
289 /* get bit specifications, at least one must be present */
290 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200291 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
292 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100293 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200294 continue;
295 }
296
Radek Krejci994b6f62015-06-18 16:47:27 +0200297 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200298 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200299 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100300 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200301 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200302 }
303 }
Radek Krejciac781922015-07-09 15:35:14 +0200304 if (!type->der->type.der && !type->info.bits.count) {
305 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100306 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200307 goto error;
308 }
Radek Krejciac781922015-07-09 15:35:14 +0200309 if (type->der->type.der && type->info.bits.count) {
310 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100311 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200312 goto error;
313 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200314
315 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100316 if (!type->info.bits.bit) {
317 LOGMEM;
318 goto error;
319 }
Radek Krejci73adb602015-07-02 18:07:40 +0200320 p = 0;
321 i = -1;
322 LY_TREE_FOR(yin->child, next) {
323 i++;
324
325 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100326 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100327 goto error;
328 }
329
Radek Krejci994b6f62015-06-18 16:47:27 +0200330 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200331 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200332 type->info.bits.count = i + 1;
333 goto error;
334 }
335
336 /* check the name uniqueness */
337 for (j = 0; j < i; j++) {
338 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100339 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200340 type->info.bits.count = i + 1;
341 goto error;
342 }
343 }
344
Radek Krejci0d70c372015-07-02 16:23:10 +0200345 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200346 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200347 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
348 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200349 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200350 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200351
Radek Krejci0d70c372015-07-02 16:23:10 +0200352 if (!strcmp(node->name, "position")) {
353 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200354 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200355
356 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200357 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100358 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200359 type->info.bits.count = i + 1;
360 goto error;
361 }
362 type->info.bits.bit[i].pos = (uint32_t)p_;
363
364 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200365 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200366 p = type->info.bits.bit[i].pos;
367 p++;
368 } else {
369 /* check that the value is unique */
370 for (j = 0; j < i; j++) {
371 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100372 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100373 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200374 type->info.bits.count = i + 1;
375 goto error;
376 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200377 }
378 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200379 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100380 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200381 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200382 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200383 }
384 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200385 /* assign value automatically */
386 if (p > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100387 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200388 type->info.bits.count = i + 1;
389 goto error;
390 }
391 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100392 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200393 p++;
394 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200395
396 /* keep them ordered by position */
397 j = i;
398 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
399 /* switch them */
400 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
401 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
402 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
403 j--;
404 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200405 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200408 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200409 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200410 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200411 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
412 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200413 continue;
414 }
415
Radek Krejcif9401c32015-06-26 16:47:36 +0200416 if (!strcmp(node->name, "range")) {
417 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100418 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200419 goto error;
420 }
421
422 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200423 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100424 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200425 goto error;
426 }
427 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100428 if (!type->info.dec64.range) {
429 LOGMEM;
430 goto error;
431 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200432 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
433
434 /* get possible substatements */
435 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
436 goto error;
437 }
438 } else if (!strcmp(node->name, "fraction-digits")) {
439 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100440 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200441 goto error;
442 }
443 GETVAL(value, node, "value");
444 v = strtol(value, NULL, 10);
445
446 /* range check */
447 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100448 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200449 goto error;
450 }
451 type->info.dec64.dig = (uint8_t)v;
452 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100453 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200454 goto error;
455 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200456 }
457
458 /* mandatory sub-statement(s) check */
459 if (!type->info.dec64.dig && !type->der->type.der) {
460 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100461 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200462 goto error;
463 }
Radek Krejci7511f402015-07-10 09:56:30 +0200464 if (type->info.dec64.dig && type->der->type.der) {
465 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100466 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200467 goto error;
468 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200469 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200471 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200472 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200473
Radek Krejci994b6f62015-06-18 16:47:27 +0200474 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200475 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200476 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
477 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100478 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200479 continue;
480 }
481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200483 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200484 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100485 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200486 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200487 }
488 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200489 if (!type->der->type.der && !type->info.enums.count) {
490 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100491 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200492 goto error;
493 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200494 if (type->der->type.der && type->info.enums.count) {
495 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100496 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200497 goto error;
498 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200499
Radek Krejci1574a8d2015-08-03 14:16:52 +0200500 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100501 if (!type->info.enums.enm) {
502 LOGMEM;
503 goto error;
504 }
Radek Krejci73adb602015-07-02 18:07:40 +0200505 v = 0;
506 i = -1;
507 LY_TREE_FOR(yin->child, next) {
508 i++;
509
510 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100511 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100512 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
513 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100514 goto error;
515 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200516 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200517 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200518 type->info.enums.count = i + 1;
519 goto error;
520 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200522 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200523 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200524 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100525 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200526 type->info.enums.count = i + 1;
527 goto error;
528 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 /* check the name uniqueness */
531 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200532 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100533 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200534 type->info.enums.count = i + 1;
535 goto error;
536 }
537 }
Radek Krejci04581c62015-05-22 21:24:00 +0200538
Radek Krejci0d70c372015-07-02 16:23:10 +0200539 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200540 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200541 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
542 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200543 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200544 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200545
Radek Krejci0d70c372015-07-02 16:23:10 +0200546 if (!strcmp(node->name, "value")) {
547 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200548 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200549
550 /* range check */
551 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100552 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200553 type->info.enums.count = i + 1;
554 goto error;
555 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200556 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200557
558 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200559 if (type->info.enums.enm[i].value > v) {
560 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200561 v++;
562 } else {
563 /* check that the value is unique */
564 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200565 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100566 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100567 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200568 type->info.enums.count = i + 1;
569 goto error;
570 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200571 }
572 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200573 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100574 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200575 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200576 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200577 }
578 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200579 /* assign value automatically */
580 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100581 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200582 type->info.enums.count = i + 1;
583 goto error;
584 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200585 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100586 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 v++;
588 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 }
590 break;
591
592 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200593 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594
595 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200596 LY_TREE_FOR_SAFE(yin->child, next, node) {
597 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
598 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100599 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200600 continue;
601 }
602
Michal Vaskoe29c6622015-11-27 15:02:31 +0100603 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100604 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200605 goto error;
606 }
607 }
608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200609 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200610 if (type->der->type.der) {
611 /* this is just a derived type with no base specified/required */
612 break;
613 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100614 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 goto error;
616 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200617 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100618 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200619 goto error;
620 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200621 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100622 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100623 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100624 if (!value) {
625 goto error;
626 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100627 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100628 lydict_remove(module->ctx, value);
629
630 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200631 goto error;
632 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200633 break;
634
635 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200636 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200637 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200638 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
639 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200640 continue;
641 }
642
Radek Krejciaf351422015-06-19 14:49:38 +0200643 if (!strcmp(node->name, "require-instance")) {
644 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100645 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200646 goto error;
647 }
648 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200649 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200650 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200651 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200652 type->info.inst.req = -1;
653 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100654 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200655 goto error;
656 }
657 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100658 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200659 goto error;
660 }
Radek Krejciaf351422015-06-19 14:49:38 +0200661 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663 break;
664
Radek Krejcif2860132015-06-20 12:37:20 +0200665 case LY_TYPE_BINARY:
666 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 case LY_TYPE_INT8:
668 case LY_TYPE_INT16:
669 case LY_TYPE_INT32:
670 case LY_TYPE_INT64:
671 case LY_TYPE_UINT8:
672 case LY_TYPE_UINT16:
673 case LY_TYPE_UINT32:
674 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200675 /* RFC 6020 9.2.4 - range */
676
677 /* length and range are actually the same restriction, so process
678 * them by this common code, we just need to differ the name and
679 * structure where the information will be stored
680 */
681 if (type->base == LY_TYPE_BINARY) {
682 restr = &type->info.binary.length;
683 name = "length";
684 } else {
685 restr = &type->info.num.range;
686 name = "range";
687 }
688
Radek Krejci73adb602015-07-02 18:07:40 +0200689 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200690 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
691 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200692 continue;
693 }
694
Radek Krejcif2860132015-06-20 12:37:20 +0200695 if (!strcmp(node->name, name)) {
696 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100697 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200698 goto error;
699 }
700
701 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200702 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100703 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200704 goto error;
705 }
706 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100707 if (!(*restr)) {
708 LOGMEM;
709 goto error;
710 }
Radek Krejcif2860132015-06-20 12:37:20 +0200711 (*restr)->expr = lydict_insert(module->ctx, value, 0);
712
713 /* get possible substatements */
714 if (read_restr_substmt(module->ctx, *restr, node)) {
715 goto error;
716 }
717 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100718 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200719 goto error;
720 }
Radek Krejcif2860132015-06-20 12:37:20 +0200721 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200722 break;
723
724 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200725 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200726 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200727 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
728 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200729 continue;
730 }
731
Michal Vasko88c29542015-11-27 14:57:53 +0100732 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200733 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100734 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200735 goto error;
736 }
737
738 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200739 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100740 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200741 if (!type->info.lref.path) {
742 goto error;
743 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100744 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200745 goto error;
746 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200747
Radek Krejcidc4c1412015-06-19 15:39:54 +0200748 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100749 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200750 goto error;
751 }
Radek Krejci73adb602015-07-02 18:07:40 +0200752 }
753
Michal Vasko88c29542015-11-27 14:57:53 +0100754 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100755 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200756 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200757 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200758 break;
759
760 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200761 /* RFC 6020 9.4.4 - length */
762 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200763 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200764 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200765 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
766 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100767 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200768 continue;
769 }
770
Radek Krejci3733a802015-06-19 13:43:21 +0200771 if (!strcmp(node->name, "length")) {
772 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100773 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200774 goto error;
775 }
776
777 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200778 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100779 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200780 goto error;
781 }
782 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100783 if (!type->info.str.length) {
784 LOGMEM;
785 goto error;
786 }
Radek Krejci3733a802015-06-19 13:43:21 +0200787 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
788
Radek Krejci5fbc9162015-06-19 14:11:11 +0200789 /* get possible sub-statements */
790 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200791 goto error;
792 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100793 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200794 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200795 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200796 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100797 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200798 goto error;
799 }
800 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200801 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200802 if (i) {
803 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100804 if (!type->info.str.patterns) {
805 LOGMEM;
806 goto error;
807 }
Radek Krejci73adb602015-07-02 18:07:40 +0200808 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100809 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200810
811 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200812 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
813 if (!precomp) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100814 LOGVAL(LYE_INREGEX, LY_VLOG_NONE, NULL, value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200815 free(type->info.str.patterns);
816 goto error;
817 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200818 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200819
Radek Krejci73adb602015-07-02 18:07:40 +0200820 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200821
822 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100823 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200824 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200825 goto error;
826 }
Radek Krejci73adb602015-07-02 18:07:40 +0200827 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200828 }
829 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200830 break;
831
832 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200833 /* RFC 6020 7.4 - type */
834 /* count number of types in union */
835 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200836 LY_TREE_FOR_SAFE(yin->child, next, node) {
837 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
838 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100839 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200840 continue;
841 }
842
Radek Krejcie4c366b2015-07-02 10:11:31 +0200843 if (!strcmp(node->name, "type")) {
844 i++;
845 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100846 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200847 goto error;
848 }
849 }
850
851 if (!i) {
852 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100853 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200854 break;
855 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100856 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200857 goto error;
858 }
859
860 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200861 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100862 if (!type->info.uni.types) {
863 LOGMEM;
864 goto error;
865 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200866 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200867 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100868 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100869 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
870 if (!rc) {
871 type->info.uni.count++;
872
873 /* union's type cannot be empty or leafref */
874 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100875 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100876 rc = -1;
877 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100878 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100879 rc = -1;
880 }
881 }
882 if (rc) {
883 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
884 for (i = 0; i < type->info.uni.count; ++i) {
885 lys_type_free(module->ctx, &type->info.uni.types[i]);
886 }
887 free(type->info.uni.types);
888 type->info.uni.types = NULL;
889 type->info.uni.count = 0;
890
891 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100892 ret = EXIT_FAILURE;
893 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100894 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200895 goto error;
896 }
Michal Vasko88c29542015-11-27 14:57:53 +0100897 }
898 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200899
Michal Vasko88c29542015-11-27 14:57:53 +0100900 case LY_TYPE_BOOL:
901 case LY_TYPE_EMPTY:
902 /* no sub-statement allowed */
903 LY_TREE_FOR(yin->child, node) {
904 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100905 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200906 goto error;
907 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200908 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 break;
910
911 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100912 LOGINT;
913 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200914 }
915
916 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200917
918error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100919 if (type->module_name) {
920 lydict_remove(module->ctx, type->module_name);
921 type->module_name = NULL;
922 }
923 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200924}
925
Michal Vasko0d343d12015-08-24 14:57:36 +0200926/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200928fill_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 +0200929{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100931 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100932 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200934 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100935 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936 goto error;
937 }
938 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100941 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 goto error;
943 }
Radek Krejcieac35532015-05-31 19:09:15 +0200944
Michal Vasko88c29542015-11-27 14:57:53 +0100945 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200946 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
947 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200948 continue;
949 }
950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100952 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100953 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 goto error;
955 }
Michal Vasko88c29542015-11-27 14:57:53 +0100956 /* HACK for unres */
957 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100958 tpdf->type.parent = tpdf;
Radek Krejci48464ed2016-03-17 15:44:09 +0100959 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent)) {
Radek Krejci73adb602015-07-02 18:07:40 +0200960 goto error;
961 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200962 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 } else if (!strcmp(node->name, "default")) {
964 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100965 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200966 goto error;
967 }
968 GETVAL(value, node, "value");
969 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
970 } else if (!strcmp(node->name, "units")) {
971 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100972 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 goto error;
974 }
975 GETVAL(value, node, "name");
976 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
977 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100978 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 goto error;
980 }
981 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200984 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100985 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200986 goto error;
987 }
Radek Krejcieac35532015-05-31 19:09:15 +0200988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200990 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100991 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200992 goto error;
993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200997
998error:
999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001001}
1002
Michal Vasko0d343d12015-08-24 14:57:36 +02001003/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001004static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001005fill_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 +02001006{
1007 const char *value;
1008 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001009 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001010
Radek Krejcib05774c2015-06-18 13:52:59 +02001011 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001012 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001013 goto error;
1014 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001015 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001016 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001017
Radek Krejci76512572015-08-04 09:47:08 +02001018 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001019 goto error;
1020 }
1021
1022 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001023 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1024 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001025 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001026 continue;
1027 }
1028
Radek Krejci3cf9e222015-06-18 11:37:50 +02001029 if (!strcmp(child->name, "if-feature")) {
1030 c++;
1031 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001032 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001033 goto error;
1034 }
1035 }
1036
1037 if (c) {
1038 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001039 if (!f->features) {
1040 LOGMEM;
1041 goto error;
1042 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001043 }
Radek Krejci73adb602015-07-02 18:07:40 +02001044 LY_TREE_FOR(yin->child, child) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001045 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001046 f->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001047 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001048 goto error;
1049 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001050 }
1051
Radek Krejci3cf9e222015-06-18 11:37:50 +02001052 return EXIT_SUCCESS;
1053
1054error:
1055
1056 return EXIT_FAILURE;
1057}
1058
Michal Vasko0d343d12015-08-24 14:57:36 +02001059/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001060static int
Radek Krejcib8048692015-08-05 13:36:34 +02001061fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001062{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001066 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001067 if (!must->expr) {
1068 goto error;
1069 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001070 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001071 goto error;
1072 }
Radek Krejci800af702015-06-02 13:46:01 +02001073
Radek Krejci41726f92015-06-19 13:11:05 +02001074 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001075
Michal Vasko77dc5652016-02-15 12:32:42 +01001076error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001078}
1079
Radek Krejci581ce772015-11-10 17:22:40 +01001080static int
Michal Vasko88c29542015-11-27 14:57:53 +01001081fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1082 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001083{
1084 int i, j;
1085 const char *value, *vaux;
1086
1087 /* get unique value (list of leafs supposed to be unique */
1088 GETVAL(value, yin, "tag");
1089
1090 /* count the number of unique leafs in the value */
1091 vaux = value;
1092 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001093 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001094 while (isspace(*vaux)) {
1095 vaux++;
1096 }
1097 }
1098 unique->expr_size++;
1099 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001100 if (!unique->expr) {
1101 LOGMEM;
1102 goto error;
1103 }
Radek Krejci581ce772015-11-10 17:22:40 +01001104
1105 for (i = 0; i < unique->expr_size; i++) {
1106 vaux = strpbrk(value, " \t\n");
1107 if (!vaux) {
1108 /* the last token, lydict_insert() will count its size on its own */
1109 vaux = value;
1110 }
1111
1112 /* store token into unique structure */
1113 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1114
1115 /* check that the expression does not repeat */
1116 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001117 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001118 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1119 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001120 goto error;
1121 }
1122 }
1123
1124 /* try to resolve leaf */
1125 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001126 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1127 goto error;
1128 }
Radek Krejci581ce772015-11-10 17:22:40 +01001129 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001130 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001131 goto error;
1132 }
1133 }
1134
1135 /* move to next token */
1136 value = vaux;
1137 while(isspace(*value)) {
1138 value++;
1139 }
1140 }
1141
1142 return EXIT_SUCCESS;
1143
1144error:
1145 return EXIT_FAILURE;
1146}
1147
Michal Vasko0d343d12015-08-24 14:57:36 +02001148/* logs directly
1149 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001150 * type: 0 - min, 1 - max
1151 */
1152static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001153deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001154{
1155 const char *value;
1156 char *endptr;
1157 unsigned long val;
1158 uint32_t *ui32val;
1159
Michal Vaskof7e57d52016-03-07 11:31:09 +01001160 /* del min/max is forbidden */
1161 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001162 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001163 goto error;
1164 }
1165
Radek Krejcieb00f512015-07-01 16:44:58 +02001166 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001167 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001168 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001169 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001170 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001171 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001172 }
Radek Krejci76512572015-08-04 09:47:08 +02001173 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001174 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001175 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001176 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001177 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001178 }
1179 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001180 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1181 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001182 goto error;
1183 }
1184
1185 GETVAL(value, node, "value");
1186 while (isspace(value[0])) {
1187 value++;
1188 }
1189
Radek Krejci0d7b2472016-02-12 11:11:03 +01001190 if (type && !strcmp(value, "unbounded")) {
1191 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001192 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001193 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001194 /* convert it to uint32_t */
1195 errno = 0;
1196 endptr = NULL;
1197 val = strtoul(value, &endptr, 10);
1198 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001199 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001200 goto error;
1201 }
1202 if (type) {
1203 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001204 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001205 } else {
1206 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001207 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001208 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001209 }
1210
1211 if (d->mod == LY_DEVIATE_ADD) {
1212 /* check that there is no current value */
1213 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001214 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1215 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001216 goto error;
1217 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001218 } else if (d->mod == LY_DEVIATE_RPL) {
1219 /* unfortunately, there is no way to check reliably that there
1220 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001221 }
1222
Michal Vaskof7e57d52016-03-07 11:31:09 +01001223 /* add (already checked) and replace */
1224 /* set new value specified in deviation */
1225 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001226
1227 return EXIT_SUCCESS;
1228
1229error:
1230
1231 return EXIT_FAILURE;
1232}
1233
Michal Vasko0d343d12015-08-24 14:57:36 +02001234/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001235static int
Michal Vasko88c29542015-11-27 14:57:53 +01001236fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1237 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001238{
1239 const char *value, **stritem;
1240 struct lyxml_elem *next, *child, *develem;
1241 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001242 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001243 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001244 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001245 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001246 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001247 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001248 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001249 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001250 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001251 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001252 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001253 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001254
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001255 ctx = module->ctx;
1256
Radek Krejcieb00f512015-07-01 16:44:58 +02001257 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001258 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001259 if (!dev->target_name) {
1260 goto error;
1261 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001262
1263 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001264 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1265 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001266 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001267 goto error;
1268 }
Michal Vaskob7b068c2016-02-16 13:51:50 +01001269 if (dev_target->module == lys_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001270 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1271 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001272 goto error;
1273 }
1274 /* mark the target module as deviated */
Michal Vaskoff006c12016-02-17 11:15:19 +01001275 dev_target->module->deviated = 1;
1276
1277 /* copy our imports to the deviated module (deviations may need them to work) */
1278 for (i = 0; i < module->imp_size; ++i) {
1279 for (j = 0; j < dev_target->module->imp_size; ++j) {
1280 if (module->imp[i].module == dev_target->module->imp[j].module) {
1281 break;
1282 }
1283 }
1284
1285 if (j < dev_target->module->imp_size) {
1286 /* import is already there */
1287 continue;
1288 }
1289
1290 /* copy the import, mark it as external */
1291 ++dev_target->module->imp_size;
1292 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1293 if (!dev_target->module->imp) {
1294 LOGMEM;
1295 goto error;
1296 }
1297 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1298 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1299 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1300 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1301 }
1302
1303 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1304 for (i = 0; i < dev_target->module->imp_size; ++i) {
1305 if (dev_target->module->imp[i].module == module) {
1306 break;
1307 }
1308 }
1309
1310 if (i == dev_target->module->imp_size) {
1311 ++dev_target->module->imp_size;
1312 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1313 if (!dev_target->module->imp) {
1314 LOGMEM;
1315 goto error;
1316 }
1317 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1318 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1319 if (module->rev_size) {
1320 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1321 } else {
1322 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1323 }
1324 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1325 } else {
1326 /* it could have been added by another deviating module that imported this deviating module */
1327 dev_target->module->imp[i].external = 2;
1328 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001329
1330 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001331 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1332 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001333 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001334 continue;
1335 }
1336
Radek Krejcieb00f512015-07-01 16:44:58 +02001337 if (!strcmp(child->name, "description")) {
1338 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001339 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001340 goto error;
1341 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001342 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001343 if (!dev->dsc) {
1344 goto error;
1345 }
1346 } else if (!strcmp(child->name, "reference")) {
1347 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001348 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001349 goto error;
1350 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001351 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001352 if (!dev->ref) {
1353 goto error;
1354 }
1355 } else if (!strcmp(child->name, "deviate")) {
1356 c_dev++;
1357
Michal Vasko345da0a2015-12-02 10:35:55 +01001358 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001359 * further processed later
1360 */
1361 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001362
Radek Krejcieb00f512015-07-01 16:44:58 +02001363 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001364 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001365 goto error;
1366 }
1367
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001368 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001369 }
1370
1371 if (c_dev) {
1372 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001373 if (!dev->deviate) {
1374 LOGMEM;
1375 goto error;
1376 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001377 }
1378
1379 LY_TREE_FOR(yin->child, develem) {
1380 /* init */
1381 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001382 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001383 c_must = 0;
1384 c_uniq = 0;
1385
1386 /* get deviation type */
1387 GETVAL(value, develem, "value");
1388 if (!strcmp(value, "not-supported")) {
1389 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1390 /* no property expected in this case */
1391 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001392 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001393 goto error;
1394 }
1395
Radek Krejci5b917642015-07-02 09:03:13 +02001396 /* and neither any other deviate statement is expected,
1397 * not-supported deviation must be the only deviation of the target
1398 */
1399 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001400 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1401 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001402 goto error;
1403 }
1404
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001405 /* you cannot remove a key leaf */
1406 if ((dev_target->nodetype == LYS_LEAF) && dev_target->parent && (dev_target->parent->nodetype == LYS_LIST)) {
1407 for (i = 0; i < ((struct lys_node_list *)dev_target->parent)->keys_size; ++i) {
1408 if (((struct lys_node_list *)dev_target->parent)->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001409 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1410 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001411 goto error;
1412 }
1413 }
1414 }
Radek Krejci5b917642015-07-02 09:03:13 +02001415
Michal Vaskoff006c12016-02-17 11:15:19 +01001416 /* unlink and store the original node */
1417 lys_node_unlink(dev_target);
1418 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001419
Radek Krejci5b917642015-07-02 09:03:13 +02001420 dev->deviate_size = 1;
1421 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001422 } else if (!strcmp(value, "add")) {
1423 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1424 } else if (!strcmp(value, "replace")) {
1425 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1426 } else if (!strcmp(value, "delete")) {
1427 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1428 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001429 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001430 goto error;
1431 }
1432 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001433 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001434
Michal Vaskoff006c12016-02-17 11:15:19 +01001435 /* store a shallow copy of the original node */
1436 if (!dev->orig_node) {
1437 memset(&tmp_unres, 0, sizeof tmp_unres);
1438 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1439 /* just to be safe */
1440 if (tmp_unres.count) {
1441 LOGINT;
1442 goto error;
1443 }
1444 }
1445
Radek Krejcieb00f512015-07-01 16:44:58 +02001446 /* process deviation properties */
1447 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001448 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1449 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001450 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001451 continue;
1452 }
1453
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001455 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001456 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001457 goto error;
1458 }
1459
1460 /* for we deviate from RFC 6020 and allow config property even it is/is not
1461 * specified in the target explicitly since config property inherits. So we expect
1462 * that config is specified in every node. But for delete, we check that the value
1463 * is the same as here in deviation
1464 */
1465 GETVAL(value, child, "value");
1466 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001467 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001468 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001469 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001470 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001471 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001472 goto error;
1473 }
1474
1475 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001476 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001477 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001478 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001479 } else { /* add and replace are the same in this case */
1480 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001481 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001482
1483 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001484 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001485 }
1486 } else if (!strcmp(child->name, "default")) {
1487 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001488 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001489 goto error;
1490 }
1491 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001492 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001493
Michal Vasko60f4b452016-02-12 11:02:55 +01001494 if (dev_target->nodetype == LYS_CHOICE) {
1495 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001496
1497 if (d->mod == LY_DEVIATE_ADD) {
1498 /* check that there is no current value */
1499 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001500 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1501 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001504 /* check collision with mandatory */
1505 if (choice->flags & LYS_MAND_TRUE) {
1506 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1507 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1508 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1509 goto error;
1510 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001511 } else if (d->mod == LY_DEVIATE_RPL) {
1512 /* check that there was a value before */
1513 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001514 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1515 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001516 goto error;
1517 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001518 }
1519
Michal Vasko3edeaf72016-02-11 13:17:43 +01001520 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001521 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001522 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001523 goto error;
1524 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001525 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001526 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001527 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1528 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001529 goto error;
1530 }
1531 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001532 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001533 if (!choice->dflt) {
1534 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001535 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001536 goto error;
1537 }
1538 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001539 } else if (dev_target->nodetype == LYS_LEAF) {
1540 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001541
1542 if (d->mod == LY_DEVIATE_ADD) {
1543 /* check that there is no current value */
1544 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001545 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1546 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001547 goto error;
1548 }
Radek Krejci841ec082016-04-05 13:05:17 +02001549 /* check collision with mandatory */
1550 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001551 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001552 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001553 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001554 goto error;
1555 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001556 }
1557
1558 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001559 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001560 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1561 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 goto error;
1563 }
1564 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001565 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 leaf->dflt = NULL;
1567 } else { /* add (already checked) and replace */
1568 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001569 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001570
1571 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001572 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001573
1574 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1575 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1576 if (!leaf_dflt_check) {
1577 LOGMEM;
1578 goto error;
1579 }
1580 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001581 }
1582 } else {
1583 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001584 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1585 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001586 goto error;
1587 }
1588 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001589 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001590 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001591 goto error;
1592 }
1593
1594 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001595 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001596 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1597 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001598 goto error;
1599 }
1600
1601 GETVAL(value, child, "value");
1602 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001603 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001604 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001605 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001607 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001608 goto error;
1609 }
1610
1611 if (d->mod == LY_DEVIATE_ADD) {
1612 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001613 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001614 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1615 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001616 goto error;
1617 }
Radek Krejci841ec082016-04-05 13:05:17 +02001618 /* check collision with default-stmt */
1619 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001620 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001621 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001622 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001623 goto error;
1624 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001625
Michal Vasko21be1b32016-03-07 12:31:34 +01001626 dev_target->flags |= d->flags & LYS_MAND_MASK;
1627 } else if (d->mod == LY_DEVIATE_RPL) {
1628 /* check that there was a value before */
1629 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001630 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1631 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001632 goto error;
1633 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001634
Michal Vasko21be1b32016-03-07 12:31:34 +01001635 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001636 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001637 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001638 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001639 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001640 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 }
1642 } else if (!strcmp(child->name, "min-elements")) {
1643 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001644 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 goto error;
1646 }
1647 f_min = 1;
1648
Michal Vasko60f4b452016-02-12 11:02:55 +01001649 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 goto error;
1651 }
1652 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001653 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001654 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001655 goto error;
1656 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001657 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001658
Michal Vasko60f4b452016-02-12 11:02:55 +01001659 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001660 goto error;
1661 }
1662 } else if (!strcmp(child->name, "must")) {
1663 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001664 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 continue;
1666 } else if (!strcmp(child->name, "type")) {
1667 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001668 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001669 goto error;
1670 }
1671
Michal Vaskof7e57d52016-03-07 11:31:09 +01001672 /* add, del type is forbidden */
1673 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001674 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001675 goto error;
1676 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001677 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001678 goto error;
1679 }
1680
Radek Krejcieb00f512015-07-01 16:44:58 +02001681 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001682 if (dev_target->nodetype == LYS_LEAF) {
1683 t = &((struct lys_node_leaf *)dev_target)->type;
1684 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1685 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001686 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001687 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1688 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001689 goto error;
1690 }
1691
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001693 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001694 /* HACK for unres */
1695 t->der = (struct lys_tpdf *)child;
Radek Krejci48464ed2016-03-17 15:44:09 +01001696 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 goto error;
1698 }
1699 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001700
1701 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1702 if (dev_target->nodetype == LYS_LEAF) {
1703 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1704 if (!leaf_dflt_check) {
1705 LOGMEM;
1706 goto error;
1707 }
1708 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1709 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001710 } else if (!strcmp(child->name, "unique")) {
1711 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001712 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 continue;
1714 } else if (!strcmp(child->name, "units")) {
1715 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001716 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001717 goto error;
1718 }
1719
1720 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001721 if (dev_target->nodetype == LYS_LEAFLIST) {
1722 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1723 } else if (dev_target->nodetype == LYS_LEAF) {
1724 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001726 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1727 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001728 goto error;
1729 }
1730
1731 /* get units value */
1732 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001733 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001734
1735 /* apply to target */
1736 if (d->mod == LY_DEVIATE_ADD) {
1737 /* check that there is no current value */
1738 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001739 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1740 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 goto error;
1742 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001743
Michal Vasko21be1b32016-03-07 12:31:34 +01001744 *stritem = lydict_insert(ctx, value, 0);
1745 } else if (d->mod == LY_DEVIATE_RPL) {
1746 /* check that there was a value before */
1747 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001748 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1749 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001750 goto error;
1751 }
1752
1753 lydict_remove(ctx, *stritem);
1754 *stritem = lydict_insert(ctx, value, 0);
1755 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 /* check values */
1757 if (*stritem != d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001758 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1759 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001760 goto error;
1761 }
1762 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001763 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001764 }
1765 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001766 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001767 goto error;
1768 }
1769
Michal Vasko88c29542015-11-27 14:57:53 +01001770 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 }
1772
1773 if (c_must) {
1774 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001775 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001776 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001777 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1778 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 break;
Radek Krejci76512572015-08-04 09:47:08 +02001780 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001781 trg_must = &((struct lys_node_container *)dev_target)->must;
1782 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001783 break;
Radek Krejci76512572015-08-04 09:47:08 +02001784 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001785 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1786 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001787 break;
Radek Krejci76512572015-08-04 09:47:08 +02001788 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001789 trg_must = &((struct lys_node_list *)dev_target)->must;
1790 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 break;
Radek Krejci76512572015-08-04 09:47:08 +02001792 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001793 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1794 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 break;
1796 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001797 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1798 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001799 goto error;
1800 }
1801
1802 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001803 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001804 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001805 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001806 } else if (d->mod == LY_DEVIATE_ADD) {
1807 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001808 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001809 if (!d->must) {
1810 LOGMEM;
1811 goto error;
1812 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001813 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001814 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001815 d->must_size = c_must;
1816 } else { /* LY_DEVIATE_DEL */
1817 d->must = calloc(c_must, sizeof *d->must);
1818 }
Michal Vasko253035f2015-12-17 16:58:13 +01001819 if (!d->must) {
1820 LOGMEM;
1821 goto error;
1822 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 }
1824 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001825 /* replace unique is forbidden */
1826 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001827 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001828 goto error;
1829 }
1830
Radek Krejcieb00f512015-07-01 16:44:58 +02001831 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001832 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001833 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1834 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001835 goto error;
1836 }
1837
Michal Vasko60f4b452016-02-12 11:02:55 +01001838 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001839 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001840 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001841 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001842 list->unique = d->unique;
1843 d->unique = &list->unique[list->unique_size];
1844 d->unique_size = c_uniq;
1845 } else { /* LY_DEVIATE_DEL */
1846 d->unique = calloc(c_uniq, sizeof *d->unique);
1847 }
Michal Vasko253035f2015-12-17 16:58:13 +01001848 if (!d->unique) {
1849 LOGMEM;
1850 goto error;
1851 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 }
1853
1854 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001855 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001856 if (!strcmp(child->name, "must")) {
1857 if (d->mod == LY_DEVIATE_DEL) {
1858 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1859 goto error;
1860 }
1861
1862 /* find must to delete, we are ok with just matching conditions */
1863 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001864 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001865 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001866 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001867 /* ... and maintain the array */
1868 (*trg_must_size)--;
1869 if (i != *trg_must_size) {
1870 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1871 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1872 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1873 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1874 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1875 }
1876 if (!(*trg_must_size)) {
1877 free(*trg_must);
1878 *trg_must = NULL;
1879 } else {
1880 (*trg_must)[*trg_must_size].expr = NULL;
1881 (*trg_must)[*trg_must_size].dsc = NULL;
1882 (*trg_must)[*trg_must_size].ref = NULL;
1883 (*trg_must)[*trg_must_size].eapptag = NULL;
1884 (*trg_must)[*trg_must_size].emsg = NULL;
1885 }
1886
1887 i = -1; /* set match flag */
1888 break;
1889 }
1890 }
1891 d->must_size++;
1892 if (i != -1) {
1893 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001894 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001895 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001896 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001897 goto error;
1898 }
1899 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001900 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1901 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001902 goto error;
1903 }
1904 (*trg_must_size)++;
1905 }
1906 } else if (!strcmp(child->name, "unique")) {
1907 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001908 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001909 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001910 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001911 goto error;
1912 }
1913
1914 /* find unique structures to delete */
1915 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001916 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001917 continue;
1918 }
1919
Radek Krejci581ce772015-11-10 17:22:40 +01001920 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001921 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 break;
1923 }
1924 }
1925
Radek Krejci581ce772015-11-10 17:22:40 +01001926 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001927 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001928 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001929 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001930 }
1931 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001932 /* ... and maintain the array */
1933 list->unique_size--;
1934 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001935 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1936 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001937 }
1938
1939 if (!list->unique_size) {
1940 free(list->unique);
1941 list->unique = NULL;
1942 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001943 list->unique[list->unique_size].expr_size = 0;
1944 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001945 }
1946
1947 i = -1; /* set match flag */
1948 break;
1949 }
1950 }
1951
1952 d->unique_size++;
1953 if (i != -1) {
1954 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001955 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1956 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 goto error;
1958 }
1959 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001960 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001961 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001962 list->unique_size++;
1963 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001964 goto error;
1965 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001966 }
1967 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001968 }
1969 }
1970
Michal Vasko43a1feb2016-03-07 12:03:02 +01001971 /* now check whether default value, if any, matches the type */
1972 for (i = 0; i < leaf_dflt_check_count; ++i) {
1973 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001974 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 +01001975 if (rc == -1) {
1976 goto error;
1977 } else if (rc == EXIT_FAILURE) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001978 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1979 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 +01001980 goto error;
1981 }
1982 }
1983 }
1984 free(leaf_dflt_check);
1985
Radek Krejcieb00f512015-07-01 16:44:58 +02001986 return EXIT_SUCCESS;
1987
1988error:
Michal Vasko34867132016-03-11 10:26:38 +01001989 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001990 return EXIT_FAILURE;
1991}
1992
Michal Vasko0d343d12015-08-24 14:57:36 +02001993/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001994static int
Radek Krejcib8048692015-08-05 13:36:34 +02001995fill_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 +02001996 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001997{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002001 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002002
Michal Vasko591e0b22015-08-13 13:53:43 +02002003 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002004 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002005 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002006 if (!aug->target_name) {
2007 goto error;
2008 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002009 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002010
Michal Vasko1d87a922015-08-21 12:57:16 +02002011 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002012 goto error;
2013 }
2014
2015 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002016 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2017 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002018 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002019 continue;
2020 }
2021
Radek Krejci3cf9e222015-06-18 11:37:50 +02002022 if (!strcmp(child->name, "if-feature")) {
2023 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002024 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002025 } else if (!strcmp(child->name, "when")) {
2026 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002027 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002028 goto error;
2029 }
2030
2031 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002032 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002033 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002034 goto error;
2035 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002036 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002037 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002038
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002039 /* check allowed data sub-statements */
2040 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002041 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002042 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002043 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002044 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002047 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002048 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002049 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002050 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002051 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002052 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002053 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002054 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002055 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002056 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002057 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002058 goto error;
2059 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002060
Radek Krejci1d82ef62015-08-07 14:44:40 +02002061 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002062 goto error;
2063 }
2064
Radek Krejci1d82ef62015-08-07 14:44:40 +02002065 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002066 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002067 }
2068
2069 if (c) {
2070 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002071 if (!aug->features) {
2072 LOGMEM;
2073 goto error;
2074 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002075 }
2076
2077 LY_TREE_FOR_SAFE(yin->child, next, child) {
2078 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002079 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002080 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002081 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002082 goto error;
2083 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002084 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002085 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002086 }
2087
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002088 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002089 * connected to the tree and adjusted (if possible right now).
2090 * However, if this is augment in a uses, it gets resolved
2091 * when the uses does and cannot be resolved now for sure
2092 * (the grouping was not yet copied into uses).
2093 */
2094 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002095 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002096 goto error;
2097 }
Michal Vasko49291b32015-08-06 09:49:41 +02002098 }
Radek Krejci106efc02015-06-10 14:36:27 +02002099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002101
2102error:
2103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002105}
2106
Michal Vasko0d343d12015-08-24 14:57:36 +02002107/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108static int
Michal Vasko0d204592015-10-07 09:50:04 +02002109fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002110{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 struct lyxml_elem *sub, *next;
2112 const char *value;
2113 char *endptr;
2114 int f_mand = 0, f_min = 0, f_max = 0;
2115 int c_must = 0;
2116 int r;
2117 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002118
Radek Krejci76512572015-08-04 09:47:08 +02002119 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 goto error;
2121 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002122
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002123 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002124 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002125 if (!rfn->target_name) {
2126 goto error;
2127 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002130 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2131 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002132 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002133 continue;
2134 }
2135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 /* limited applicability */
2137 if (!strcmp(sub->name, "default")) {
2138 /* leaf or choice */
2139 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002140 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 goto error;
2142 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 /* check possibility of statements combination */
2145 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002146 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002148 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2149 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 goto error;
2151 }
2152 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002153 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 GETVAL(value, sub, "value");
2157 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2158 } else if (!strcmp(sub->name, "mandatory")) {
2159 /* leaf, choice or anyxml */
2160 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002161 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 goto error;
2163 }
2164 /* just checking the flags in leaf is not sufficient, we would allow
2165 * multiple mandatory statements with the "false" value
2166 */
2167 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 /* check possibility of statements combination */
2170 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002171 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002173 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2174 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 goto error;
2176 }
2177 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002178 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 GETVAL(value, sub, "value");
2182 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002183 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002185 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002187 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 goto error;
2189 }
2190 } else if (!strcmp(sub->name, "min-elements")) {
2191 /* list or leaf-list */
2192 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002193 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 goto error;
2195 }
2196 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 /* check possibility of statements combination */
2199 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002200 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002202 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2203 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 goto error;
2205 }
2206 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002207 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 GETVAL(value, sub, "value");
2211 while (isspace(value[0])) {
2212 value++;
2213 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 /* convert it to uint32_t */
2216 errno = 0;
2217 endptr = NULL;
2218 val = strtoul(value, &endptr, 10);
2219 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002220 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 goto error;
2222 }
2223 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002224 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 } else if (!strcmp(sub->name, "max-elements")) {
2226 /* list or leaf-list */
2227 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002228 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 goto error;
2230 }
2231 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 /* check possibility of statements combination */
2234 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002235 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002237 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2238 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 goto error;
2240 }
2241 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002242 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 GETVAL(value, sub, "value");
2246 while (isspace(value[0])) {
2247 value++;
2248 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002249
Radek Krejci0d7b2472016-02-12 11:11:03 +01002250 if (!strcmp(value, "unbounded")) {
2251 rfn->mod.list.max = 0;
2252 } else {
2253 /* convert it to uint32_t */
2254 errno = 0;
2255 endptr = NULL;
2256 val = strtoul(value, &endptr, 10);
2257 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002258 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002259 goto error;
2260 }
2261 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002263 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 } else if (!strcmp(sub->name, "presence")) {
2265 /* container */
2266 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002267 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 goto error;
2269 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 /* check possibility of statements combination */
2272 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002273 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002275 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2276 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 goto error;
2278 }
2279 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002280 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 GETVAL(value, sub, "value");
2284 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2285 } else if (!strcmp(sub->name, "must")) {
2286 /* leaf-list, list, container or anyxml */
2287 /* check possibility of statements combination */
2288 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002289 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002291 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2292 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 goto error;
2294 }
2295 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002296 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002300 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002303 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 goto error;
2305 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002306
Michal Vasko345da0a2015-12-02 10:35:55 +01002307 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 /* process nodes with cardinality of 0..n */
2311 if (c_must) {
2312 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002313 if (!rfn->must) {
2314 LOGMEM;
2315 goto error;
2316 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 }
Radek Krejci73adb602015-07-02 18:07:40 +02002318 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002319 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2320 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002321 if (r) {
2322 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002327
2328error:
2329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002331}
2332
Michal Vasko0d343d12015-08-24 14:57:36 +02002333/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334static int
Radek Krejcib8048692015-08-05 13:36:34 +02002335fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002336{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 struct lyxml_elem *child;
2338 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002341 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2342 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002343 continue;
2344 }
2345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 if (!strcmp(child->name, "prefix")) {
2347 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002348 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 goto error;
2350 }
2351 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2352 } else if (!strcmp(child->name, "revision-date")) {
2353 if (imp->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(imp->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 /* check mandatory information */
2369 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002370 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 goto error;
2372 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002375
Pavol Vicane994fda2016-03-22 10:47:58 +01002376 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002377
2378error:
2379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002381}
2382
Michal Vasko0d343d12015-08-24 14:57:36 +02002383/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002385fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2386 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002387{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002388 struct lyxml_elem *child;
2389 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002392 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2393 /* garbage */
2394 continue;
2395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002396 if (!strcmp(child->name, "revision-date")) {
2397 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002398 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399 goto error;
2400 }
2401 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002402 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 goto error;
2404 }
2405 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2406 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002407 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408 goto error;
2409 }
2410 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002413
Pavol Vican0adf01d2016-03-22 12:29:33 +01002414 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002415
2416error:
2417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002419}
2420
Michal Vasko0d343d12015-08-24 14:57:36 +02002421/* logs directly
2422 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002423 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002424 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002425 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002426 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427static int
Radek Krejcib8048692015-08-05 13:36:34 +02002428read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002429 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002430{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 const char *value;
2432 struct lyxml_elem *sub, *next;
2433 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002436 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 if (opt & OPT_IDENT) {
2440 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002441 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 goto error;
2443 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002444 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002446
Radek Krejci6764bb32015-07-03 15:16:04 +02002447 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002448 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002449 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002450 }
2451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 /* process local parameters */
2453 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002454 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002455 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002456 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002457 continue;
2458 }
2459 if (strcmp(sub->ns->value, LY_NSYIN)) {
2460 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002461 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002462 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002463 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002464 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002465 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002466 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002467 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002468 goto error;
2469 }
2470 }
2471
2472 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002473 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002474 continue;
2475 }
2476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002478 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002479 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 goto error;
2481 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002482 node->dsc = read_yin_subnode(ctx, sub, "text");
2483 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002484 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 }
2486 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002487 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002488 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 goto error;
2490 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002491 node->ref = read_yin_subnode(ctx, sub, "text");
2492 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002493 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 }
2495 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002496 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002497 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002498 goto error;
2499 }
2500 GETVAL(value, sub, "value");
2501 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002502 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002504 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002506 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002507 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002508 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002509 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 }
2511 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002512 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002513 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002514 goto error;
2515 }
2516 GETVAL(value, sub, "value");
2517 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002518 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002519 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002520 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002521 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002522 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002523 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524 }
2525 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002526 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 continue;
2528 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002529 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002531
Radek Krejci1d82ef62015-08-07 14:44:40 +02002532 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 /* get config flag from parent */
2534 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002535 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002536 } else {
2537 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002538 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539 }
2540 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002542 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002543
2544error:
2545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002547}
2548
Michal Vasko0d343d12015-08-24 14:57:36 +02002549/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002550static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002551read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002552{
Radek Krejci76512572015-08-04 09:47:08 +02002553 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002554 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002555 const char *value;
2556
2557 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002558 if (!retval) {
2559 LOGMEM;
2560 return NULL;
2561 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002562
2563 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002564 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002565 if (!retval->cond) {
2566 goto error;
2567 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002568 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002569 goto error;
2570 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002571
Radek Krejci73adb602015-07-02 18:07:40 +02002572 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002573 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2574 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002575 continue;
2576 }
2577
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002578 if (!strcmp(child->name, "description")) {
2579 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002580 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002581 goto error;
2582 }
2583 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2584 if (!retval->dsc) {
2585 goto error;
2586 }
2587 } else if (!strcmp(child->name, "reference")) {
2588 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002589 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002590 goto error;
2591 }
2592 retval->ref = read_yin_subnode(module->ctx, child, "text");
2593 if (!retval->ref) {
2594 goto error;
2595 }
2596 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002597 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002598 goto error;
2599 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002600 }
2601
2602 return retval;
2603
2604error:
2605
Michal Vasko0308dd62015-10-07 09:14:40 +02002606 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002607 return NULL;
2608}
2609
Michal Vasko0d343d12015-08-24 14:57:36 +02002610/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002611static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002612read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2613 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002614{
Michal Vasko29fc0182015-08-24 15:02:39 +02002615 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002616 struct lys_node_case *cs;
2617 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002618 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002619
Radek Krejcie867c852015-08-27 09:52:34 +02002620 /* init */
2621 memset(&root, 0, sizeof root);
2622
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002624 if (!cs) {
2625 LOGMEM;
2626 return NULL;
2627 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002628 cs->nodetype = LYS_CASE;
2629 cs->prev = (struct lys_node *)cs;
2630 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002631
Radek Krejci6a113852015-07-03 16:04:20 +02002632 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 goto error;
2634 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002635
Radek Krejcia9544502015-08-14 08:24:29 +02002636 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2637
Michal Vasko3a0043f2015-08-12 12:11:30 +02002638 /* insert the node into the schema tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +01002639 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002640 goto error;
2641 }
2642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 /* process choice's specific children */
2644 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002645 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2646 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002647 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002648 continue;
2649 }
2650
Michal Vasko29fc0182015-08-24 15:02:39 +02002651 if (!strcmp(sub->name, "container") ||
2652 !strcmp(sub->name, "leaf-list") ||
2653 !strcmp(sub->name, "leaf") ||
2654 !strcmp(sub->name, "list") ||
2655 !strcmp(sub->name, "uses") ||
2656 !strcmp(sub->name, "choice") ||
2657 !strcmp(sub->name, "anyxml")) {
2658
Michal Vaskof3930de2015-10-22 12:03:59 +02002659 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002660 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002661 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002662 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002663 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002664 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002665 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002666 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002667 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002668 goto error;
2669 }
2670
Radek Krejci1d82ef62015-08-07 14:44:40 +02002671 cs->when = read_yin_when(module, sub);
2672 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002673 goto error;
2674 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002675
Michal Vasko345da0a2015-12-02 10:35:55 +01002676 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002677 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002678 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002681 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002682
Radek Krejci3cf9e222015-06-18 11:37:50 +02002683 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002684 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002685 if (!cs->features) {
2686 LOGMEM;
2687 goto error;
2688 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002689 }
Radek Krejci73adb602015-07-02 18:07:40 +02002690 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002691 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002692 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002693 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002694 goto error;
2695 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002696 }
Radek Krejcib388c152015-06-04 17:03:03 +02002697
Michal Vasko29fc0182015-08-24 15:02:39 +02002698 /* last part - process data nodes */
2699 LY_TREE_FOR_SAFE(root.child, next, sub) {
2700 if (!strcmp(sub->name, "container")) {
2701 node = read_yin_container(module, retval, sub, resolve, unres);
2702 } else if (!strcmp(sub->name, "leaf-list")) {
2703 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2704 } else if (!strcmp(sub->name, "leaf")) {
2705 node = read_yin_leaf(module, retval, sub, resolve, unres);
2706 } else if (!strcmp(sub->name, "list")) {
2707 node = read_yin_list(module, retval, sub, resolve, unres);
2708 } else if (!strcmp(sub->name, "choice")) {
2709 node = read_yin_choice(module, retval, sub, resolve, unres);
2710 } else if (!strcmp(sub->name, "uses")) {
2711 node = read_yin_uses(module, retval, sub, resolve, unres);
2712 } else if (!strcmp(sub->name, "anyxml")) {
2713 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2714 }
2715 if (!node) {
2716 goto error;
2717 }
2718
Michal Vasko345da0a2015-12-02 10:35:55 +01002719 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002720 }
2721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002723
2724error:
2725
Michal Vasko29fc0182015-08-24 15:02:39 +02002726 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002727 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002728 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002729 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002732}
2733
Michal Vasko0d343d12015-08-24 14:57:36 +02002734/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002735static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002736read_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 +02002737{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 struct lyxml_elem *sub, *next;
2739 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002740 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002741 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002742 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002743 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002746 if (!choice) {
2747 LOGMEM;
2748 return NULL;
2749 }
Radek Krejci76512572015-08-04 09:47:08 +02002750 choice->nodetype = LYS_CHOICE;
2751 choice->prev = (struct lys_node *)choice;
2752 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002753
Michal Vaskoe0c59842015-09-24 13:52:20 +02002754 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2755 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002756 goto error;
2757 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002758
Radek Krejcia9544502015-08-14 08:24:29 +02002759 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2760
Michal Vasko3a0043f2015-08-12 12:11:30 +02002761 /* insert the node into the schema tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +01002762 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002763 goto error;
2764 }
2765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 /* process choice's specific children */
2767 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002768 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2769 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002770 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002771 continue;
2772 }
2773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002775 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002776 goto error;
2777 }
2778 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002779 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002780 goto error;
2781 }
2782 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002783 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002784 goto error;
2785 }
2786 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002787 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 goto error;
2789 }
2790 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002791 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 goto error;
2793 }
2794 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002795 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002796 goto error;
2797 }
2798 } else if (!strcmp(sub->name, "default")) {
2799 if (dflt_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002800 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 goto error;
2802 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002803 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002804 } else if (!strcmp(sub->name, "mandatory")) {
2805 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002806 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 goto error;
2808 }
2809 /* just checking the flags in leaf is not sufficient, we would allow
2810 * multiple mandatory statements with the "false" value
2811 */
2812 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 GETVAL(value, sub, "value");
2815 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002816 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002817 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002818 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002819 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002820 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 goto error;
2822 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002823 } else if (!strcmp(sub->name, "when")) {
2824 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002825 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002826 goto error;
2827 }
2828
2829 choice->when = read_yin_when(module, sub);
2830 if (!choice->when) {
2831 goto error;
2832 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002833 } else if (!strcmp(sub->name, "if-feature")) {
2834 c_ftrs++;
2835
Michal Vasko345da0a2015-12-02 10:35:55 +01002836 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002837 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002839 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002842
Radek Krejci1d82ef62015-08-07 14:44:40 +02002843 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002844 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002845 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002846
Radek Krejci3cf9e222015-06-18 11:37:50 +02002847 if (c_ftrs) {
2848 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002849 if (!choice->features) {
2850 LOGMEM;
2851 goto error;
2852 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002853 }
2854
Radek Krejci73adb602015-07-02 18:07:40 +02002855 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002856 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002857 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002858 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002859 goto error;
2860 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002861 }
2862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002863 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002864 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002865 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2866 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002867 goto error;
2868 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002870 /* link default with the case */
2871 if (dflt_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002872 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002873 goto error;
2874 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002878
2879error:
2880
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002881 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002884}
2885
Michal Vasko0d343d12015-08-24 14:57:36 +02002886/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002887static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002888read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002889 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002890{
Radek Krejci76512572015-08-04 09:47:08 +02002891 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002892 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 struct lyxml_elem *sub, *next;
2894 const char *value;
2895 int r;
2896 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002897 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002900 if (!anyxml) {
2901 LOGMEM;
2902 return NULL;
2903 }
Radek Krejci76512572015-08-04 09:47:08 +02002904 anyxml->nodetype = LYS_ANYXML;
2905 anyxml->prev = (struct lys_node *)anyxml;
2906 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002907
Michal Vaskoe0c59842015-09-24 13:52:20 +02002908 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2909 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 goto error;
2911 }
Radek Krejci863c2852015-06-03 15:47:11 +02002912
Radek Krejcia9544502015-08-14 08:24:29 +02002913 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002914
Michal Vasko4f0dad02016-02-15 14:08:23 +01002915 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002916 goto error;
2917 }
2918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002920 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2921 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002922 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002923 continue;
2924 }
2925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 if (!strcmp(sub->name, "mandatory")) {
2927 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002928 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 goto error;
2930 }
2931 /* just checking the flags in leaf is not sufficient, we would allow
2932 * multiple mandatory statements with the "false" value
2933 */
2934 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 GETVAL(value, sub, "value");
2937 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002938 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002939 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002940 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002941 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002942 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 goto error;
2944 }
2945 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002946 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002947 } else if (!strcmp(sub->name, "when")) {
2948 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002949 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002950 goto error;
2951 }
2952
2953 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002954 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002955 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002956 goto error;
2957 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002958 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 } else if (!strcmp(sub->name, "must")) {
2960 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002961 } else if (!strcmp(sub->name, "if-feature")) {
2962 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002965 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 }
2968 }
Radek Krejci863c2852015-06-03 15:47:11 +02002969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002970 /* middle part - process nodes with cardinality of 0..n */
2971 if (c_must) {
2972 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002973 if (!anyxml->must) {
2974 LOGMEM;
2975 goto error;
2976 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002978 if (c_ftrs) {
2979 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002980 if (!anyxml->features) {
2981 LOGMEM;
2982 goto error;
2983 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002984 }
Radek Krejci863c2852015-06-03 15:47:11 +02002985
Radek Krejci73adb602015-07-02 18:07:40 +02002986 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002988 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2989 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 if (r) {
2991 goto error;
2992 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002993 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002994 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002995 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002996 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002997 goto error;
2998 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 }
Radek Krejci863c2852015-06-03 15:47:11 +02003001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003003
3004error:
3005
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003006 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003009}
3010
Michal Vasko0d343d12015-08-24 14:57:36 +02003011/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003012static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003013read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003014 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003015{
Radek Krejci76512572015-08-04 09:47:08 +02003016 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003017 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 struct lyxml_elem *sub, *next;
3019 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003020 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003021 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003023 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003024 if (!leaf) {
3025 LOGMEM;
3026 return NULL;
3027 }
Radek Krejci76512572015-08-04 09:47:08 +02003028 leaf->nodetype = LYS_LEAF;
3029 leaf->prev = (struct lys_node *)leaf;
3030 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003031
Michal Vaskoe0c59842015-09-24 13:52:20 +02003032 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3033 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 goto error;
3035 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003036
Radek Krejcia9544502015-08-14 08:24:29 +02003037 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003038
Michal Vasko4f0dad02016-02-15 14:08:23 +01003039 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003040 goto error;
3041 }
3042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003044 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3045 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003046 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003047 continue;
3048 }
3049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003051 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003052 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 goto error;
3054 }
Michal Vasko88c29542015-11-27 14:57:53 +01003055 /* HACK for unres */
3056 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003057 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci48464ed2016-03-17 15:44:09 +01003058 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003059 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 goto error;
3061 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003062 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 } else if (!strcmp(sub->name, "default")) {
3064 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003065 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 goto error;
3067 }
3068 GETVAL(value, sub, "value");
3069 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3070 } else if (!strcmp(sub->name, "units")) {
3071 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003072 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 goto error;
3074 }
3075 GETVAL(value, sub, "name");
3076 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3077 } else if (!strcmp(sub->name, "mandatory")) {
3078 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003079 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 goto error;
3081 }
3082 /* just checking the flags in leaf is not sufficient, we would allow
3083 * multiple mandatory statements with the "false" value
3084 */
3085 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 GETVAL(value, sub, "value");
3088 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003089 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003090 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003091 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003092 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003093 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 goto error;
3095 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003096 } else if (!strcmp(sub->name, "when")) {
3097 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003098 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003099 goto error;
3100 }
3101
3102 leaf->when = read_yin_when(module, sub);
3103 if (!leaf->when) {
3104 goto error;
3105 }
3106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003108 c_must++;
3109 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003110 } else if (!strcmp(sub->name, "if-feature")) {
3111 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003112 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003114 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003115 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003118
Michal Vasko88c29542015-11-27 14:57:53 +01003119 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003120 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003123 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003124 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003127 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003128 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003129 goto error;
3130 }
Radek Krejci841ec082016-04-05 13:05:17 +02003131 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003132 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003133 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003134 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003135 goto error;
3136 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003137 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 /* middle part - process nodes with cardinality of 0..n */
3140 if (c_must) {
3141 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003142 if (!leaf->must) {
3143 LOGMEM;
3144 goto error;
3145 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003146 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003147 if (c_ftrs) {
3148 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003149 if (!leaf->features) {
3150 LOGMEM;
3151 goto error;
3152 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003153 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003154
Radek Krejci73adb602015-07-02 18:07:40 +02003155 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003157 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3158 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 if (r) {
3160 goto error;
3161 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003162 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003163 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003164 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003165 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003166 goto error;
3167 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003172
3173error:
3174
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003175 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003177 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003178}
3179
Michal Vasko0d343d12015-08-24 14:57:36 +02003180/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003181static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003182read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003183 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003184{
Radek Krejci76512572015-08-04 09:47:08 +02003185 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003186 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 struct lyxml_elem *sub, *next;
3188 const char *value;
3189 char *endptr;
3190 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003191 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003192 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003196 if (!llist) {
3197 LOGMEM;
3198 return NULL;
3199 }
Radek Krejci76512572015-08-04 09:47:08 +02003200 llist->nodetype = LYS_LEAFLIST;
3201 llist->prev = (struct lys_node *)llist;
3202 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003203
Michal Vaskoe0c59842015-09-24 13:52:20 +02003204 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3205 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003206 goto error;
3207 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003208
Radek Krejcia9544502015-08-14 08:24:29 +02003209 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003210
Michal Vasko4f0dad02016-02-15 14:08:23 +01003211 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003212 goto error;
3213 }
3214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003216 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3217 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003218 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003219 continue;
3220 }
3221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003223 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
Michal Vasko88c29542015-11-27 14:57:53 +01003227 /* HACK for unres */
3228 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003229 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci48464ed2016-03-17 15:44:09 +01003230 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003231 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 goto error;
3233 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003234 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 } else if (!strcmp(sub->name, "units")) {
3236 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003237 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 goto error;
3239 }
3240 GETVAL(value, sub, "name");
3241 llist->units = lydict_insert(module->ctx, value, strlen(value));
3242 } else if (!strcmp(sub->name, "ordered-by")) {
3243 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003244 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 goto error;
3246 }
3247 /* just checking the flags in llist is not sufficient, we would
3248 * allow multiple ordered-by statements with the "system" value
3249 */
3250 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003251
Radek Krejci1574a8d2015-08-03 14:16:52 +02003252 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3254 * state data
3255 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003256 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 continue;
3258 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 GETVAL(value, sub, "value");
3261 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003262 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003264 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003266 } /* else system is the default value, so we can ignore it */
3267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 } else if (!strcmp(sub->name, "must")) {
3269 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003270 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003271 } else if (!strcmp(sub->name, "if-feature")) {
3272 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003274
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 } else if (!strcmp(sub->name, "min-elements")) {
3276 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003277 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 goto error;
3279 }
3280 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003282 GETVAL(value, sub, "value");
3283 while (isspace(value[0])) {
3284 value++;
3285 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003287 /* convert it to uint32_t */
3288 errno = 0;
3289 endptr = NULL;
3290 val = strtoul(value, &endptr, 10);
3291 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003292 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 goto error;
3294 }
3295 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003296 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003297 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3298 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003299 goto error;
3300 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 } else if (!strcmp(sub->name, "max-elements")) {
3302 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003303 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 goto error;
3305 }
3306 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 GETVAL(value, sub, "value");
3309 while (isspace(value[0])) {
3310 value++;
3311 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003312
Radek Krejci0d7b2472016-02-12 11:11:03 +01003313 if (!strcmp(value, "unbounded")) {
3314 llist->max = 0;
3315 } else {
3316 /* convert it to uint32_t */
3317 errno = 0;
3318 endptr = NULL;
3319 val = strtoul(value, &endptr, 10);
3320 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003321 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003322 goto error;
3323 }
3324 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003325 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003326 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3327 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003328 goto error;
3329 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003330 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003331 } else if (!strcmp(sub->name, "when")) {
3332 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003333 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003334 goto error;
3335 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003336
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003337 llist->when = read_yin_when(module, sub);
3338 if (!llist->when) {
3339 goto error;
3340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003342 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003345
Michal Vasko88c29542015-11-27 14:57:53 +01003346 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003347 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003350 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003351 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 /* middle part - process nodes with cardinality of 0..n */
3356 if (c_must) {
3357 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003358 if (!llist->must) {
3359 LOGMEM;
3360 goto error;
3361 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003363 if (c_ftrs) {
3364 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003365 if (!llist->features) {
3366 LOGMEM;
3367 goto error;
3368 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003369 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003370
Radek Krejci73adb602015-07-02 18:07:40 +02003371 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003372 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003373 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3374 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 if (r) {
3376 goto error;
3377 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003378 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003379 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003380 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003381 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003382 goto error;
3383 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003388
3389error:
3390
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003391 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003394}
3395
Michal Vasko0d343d12015-08-24 14:57:36 +02003396/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003397static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003398read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3399 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003400{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003401 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003402 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003404 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003405 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003407 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 char *auxs;
3409 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 /* init */
3412 memset(&root, 0, sizeof root);
3413 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003416 if (!list) {
3417 LOGMEM;
3418 return NULL;
3419 }
Radek Krejci76512572015-08-04 09:47:08 +02003420 list->nodetype = LYS_LIST;
3421 list->prev = (struct lys_node *)list;
3422 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003423
Michal Vaskoe0c59842015-09-24 13:52:20 +02003424 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3425 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 goto error;
3427 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003428
Radek Krejcia9544502015-08-14 08:24:29 +02003429 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 /* process list's specific children */
3432 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003433 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3434 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003435 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003436 continue;
3437 }
3438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 /* data statements */
3440 if (!strcmp(sub->name, "container") ||
3441 !strcmp(sub->name, "leaf-list") ||
3442 !strcmp(sub->name, "leaf") ||
3443 !strcmp(sub->name, "list") ||
3444 !strcmp(sub->name, "choice") ||
3445 !strcmp(sub->name, "uses") ||
3446 !strcmp(sub->name, "grouping") ||
3447 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003448 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003449 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 /* array counters */
3452 } else if (!strcmp(sub->name, "key")) {
3453 /* check cardinality 0..1 */
3454 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003455 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 /* count the number of keys */
3460 GETVAL(value, sub, "value");
3461 key_str = value;
3462 while ((value = strpbrk(value, " \t\n"))) {
3463 list->keys_size++;
3464 while (isspace(*value)) {
3465 value++;
3466 }
3467 }
3468 list->keys_size++;
3469 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003470 if (!list->keys) {
3471 LOGMEM;
3472 goto error;
3473 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 } else if (!strcmp(sub->name, "unique")) {
3475 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003476 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003477 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 } else if (!strcmp(sub->name, "typedef")) {
3479 c_tpdf++;
3480 } else if (!strcmp(sub->name, "must")) {
3481 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003482 } else if (!strcmp(sub->name, "if-feature")) {
3483 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 /* optional stetments */
3486 } else if (!strcmp(sub->name, "ordered-by")) {
3487 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003488 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 goto error;
3490 }
3491 /* just checking the flags in llist is not sufficient, we would
3492 * allow multiple ordered-by statements with the "system" value
3493 */
3494 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003495
Radek Krejci1574a8d2015-08-03 14:16:52 +02003496 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3498 * state data
3499 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003500 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 continue;
3502 }
Radek Krejci345ad742015-06-03 11:04:18 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 GETVAL(value, sub, "value");
3505 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003506 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003508 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 goto error;
3510 }
3511 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003512 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 } else if (!strcmp(sub->name, "min-elements")) {
3514 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003515 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003516 goto error;
3517 }
3518 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 GETVAL(value, sub, "value");
3521 while (isspace(value[0])) {
3522 value++;
3523 }
Radek Krejci345ad742015-06-03 11:04:18 +02003524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 /* convert it to uint32_t */
3526 errno = 0;
3527 auxs = NULL;
3528 val = strtoul(value, &auxs, 10);
3529 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003530 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 goto error;
3532 }
3533 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003534 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003535 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3536 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003537 lyxml_free(module->ctx, sub);
3538 goto error;
3539 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003540 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 } else if (!strcmp(sub->name, "max-elements")) {
3542 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003543 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 goto error;
3545 }
3546 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003548 GETVAL(value, sub, "value");
3549 while (isspace(value[0])) {
3550 value++;
3551 }
Radek Krejci345ad742015-06-03 11:04:18 +02003552
Radek Krejci0d7b2472016-02-12 11:11:03 +01003553 if (!strcmp(value, "unbounded")) {
3554 list->max = 0;;
3555 } else {
3556 /* convert it to uint32_t */
3557 errno = 0;
3558 auxs = NULL;
3559 val = strtoul(value, &auxs, 10);
3560 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003561 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003562 goto error;
3563 }
3564 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003565 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003566 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003568 goto error;
3569 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003571 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003572 } else if (!strcmp(sub->name, "when")) {
3573 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003574 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003575 goto error;
3576 }
3577
3578 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003579 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003580 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003581 goto error;
3582 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003583 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003584 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003585 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003586 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 }
3588 }
Radek Krejci345ad742015-06-03 11:04:18 +02003589
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003591 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003592 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 goto error;
3594 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3597 if (c_tpdf) {
3598 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003599 if (!list->tpdf) {
3600 LOGMEM;
3601 goto error;
3602 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003604 if (c_must) {
3605 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003606 if (!list->must) {
3607 LOGMEM;
3608 goto error;
3609 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003610 }
3611 if (c_ftrs) {
3612 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003613 if (!list->features) {
3614 LOGMEM;
3615 goto error;
3616 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003617 }
Radek Krejci73adb602015-07-02 18:07:40 +02003618 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003620 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3621 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 if (r) {
3623 goto error;
3624 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003625 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003626 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003627 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003628 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003629 goto error;
3630 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003631 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003632 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3633 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003634 if (r) {
3635 goto error;
3636 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 }
3638 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003639
Michal Vasko4f0dad02016-02-15 14:08:23 +01003640 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003641 goto error;
3642 }
3643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003644 /* last part - process data nodes */
3645 LY_TREE_FOR_SAFE(root.child, next, sub) {
3646 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003647 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003648 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003649 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003651 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003653 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003655 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003657 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003658 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003659 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003661 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003662 } else {
3663 LOGINT;
3664 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003666 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 goto error;
3668 }
Radek Krejci73adb602015-07-02 18:07:40 +02003669
Michal Vasko345da0a2015-12-02 10:35:55 +01003670 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003672
Radek Krejci461efb92016-02-12 15:52:18 +01003673 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003674 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003675 goto error;
3676 }
3677 } /* 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 +02003678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 /* process unique statements */
3680 if (c_uniq) {
3681 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003682 if (!list->unique) {
3683 LOGMEM;
3684 goto error;
3685 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003686
Radek Krejci461efb92016-02-12 15:52:18 +01003687 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3688 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3689 list->unique_size++;
3690 if (r) {
3691 goto error;
3692 }
3693
3694 lyxml_free(module->ctx, sub);
3695 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003699
3700error:
3701
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003702 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003704 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 }
3706 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003707 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003711}
3712
Michal Vasko0d343d12015-08-24 14:57:36 +02003713/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003714static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003715read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3716 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003717{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003719 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003720 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003721 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 const char *value;
3723 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003724 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 /* init */
3727 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003730 if (!cont) {
3731 LOGMEM;
3732 return NULL;
3733 }
Radek Krejci76512572015-08-04 09:47:08 +02003734 cont->nodetype = LYS_CONTAINER;
3735 cont->prev = (struct lys_node *)cont;
3736 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003737
Michal Vaskoe0c59842015-09-24 13:52:20 +02003738 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3739 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 goto error;
3741 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003742
Radek Krejcia9544502015-08-14 08:24:29 +02003743 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 /* process container's specific children */
3746 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003747 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003748 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003749 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003750 continue;
3751 }
3752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 if (!strcmp(sub->name, "presence")) {
3754 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003755 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 goto error;
3757 }
3758 GETVAL(value, sub, "value");
3759 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003760
Michal Vasko345da0a2015-12-02 10:35:55 +01003761 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003762 } else if (!strcmp(sub->name, "when")) {
3763 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003764 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003765 goto error;
3766 }
3767
3768 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003769 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003770 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003771 goto error;
3772 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003773 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003775 /* data statements */
3776 } else if (!strcmp(sub->name, "container") ||
3777 !strcmp(sub->name, "leaf-list") ||
3778 !strcmp(sub->name, "leaf") ||
3779 !strcmp(sub->name, "list") ||
3780 !strcmp(sub->name, "choice") ||
3781 !strcmp(sub->name, "uses") ||
3782 !strcmp(sub->name, "grouping") ||
3783 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003784 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003785 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 /* array counters */
3788 } else if (!strcmp(sub->name, "typedef")) {
3789 c_tpdf++;
3790 } else if (!strcmp(sub->name, "must")) {
3791 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003792 } else if (!strcmp(sub->name, "if-feature")) {
3793 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003794 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003795 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003796 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 }
3798 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3801 if (c_tpdf) {
3802 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003803 if (!cont->tpdf) {
3804 LOGMEM;
3805 goto error;
3806 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 }
3808 if (c_must) {
3809 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003810 if (!cont->must) {
3811 LOGMEM;
3812 goto error;
3813 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003815 if (c_ftrs) {
3816 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003817 if (!cont->features) {
3818 LOGMEM;
3819 goto error;
3820 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003821 }
Radek Krejci800af702015-06-02 13:46:01 +02003822
Radek Krejci73adb602015-07-02 18:07:40 +02003823 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003825 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3826 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 if (r) {
3828 goto error;
3829 }
3830 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003831 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3832 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003833 if (r) {
3834 goto error;
3835 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003836 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003837 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003838 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003839 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003840 goto error;
3841 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003842 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003844
Michal Vasko4f0dad02016-02-15 14:08:23 +01003845 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003846 goto error;
3847 }
3848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 /* last part - process data nodes */
3850 LY_TREE_FOR_SAFE(root.child, next, sub) {
3851 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003852 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003856 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003858 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003860 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003862 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003864 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003866 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003867 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003868 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 goto error;
3870 }
Radek Krejci73adb602015-07-02 18:07:40 +02003871
Michal Vasko345da0a2015-12-02 10:35:55 +01003872 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003876
3877error:
3878
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003879 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003881 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003885}
3886
Michal Vasko0d343d12015-08-24 14:57:36 +02003887/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003888static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003889read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003890 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003893 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003894 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003895 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 int r;
3897 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 /* init */
3900 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003903 if (!grp) {
3904 LOGMEM;
3905 return NULL;
3906 }
Radek Krejci76512572015-08-04 09:47:08 +02003907 grp->nodetype = LYS_GROUPING;
3908 grp->prev = (struct lys_node *)grp;
3909 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003910
Michal Vasko71e1aa82015-08-12 12:17:51 +02003911 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 goto error;
3913 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003914
Radek Krejcia9544502015-08-14 08:24:29 +02003915 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3916
Radek Krejci1d82ef62015-08-07 14:44:40 +02003917 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003918 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3919 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003920 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003921 continue;
3922 }
3923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 /* data statements */
3925 if (!strcmp(sub->name, "container") ||
3926 !strcmp(sub->name, "leaf-list") ||
3927 !strcmp(sub->name, "leaf") ||
3928 !strcmp(sub->name, "list") ||
3929 !strcmp(sub->name, "choice") ||
3930 !strcmp(sub->name, "uses") ||
3931 !strcmp(sub->name, "grouping") ||
3932 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003933 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003934 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 /* array counters */
3937 } else if (!strcmp(sub->name, "typedef")) {
3938 c_tpdf++;
3939 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003940 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003941 goto error;
3942 }
3943 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3946 if (c_tpdf) {
3947 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003948 if (!grp->tpdf) {
3949 LOGMEM;
3950 goto error;
3951 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003953 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003954 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3955 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003956 if (r) {
3957 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
Michal Vasko4f0dad02016-02-15 14:08:23 +01003961 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003962 goto error;
3963 }
3964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 /* last part - process data nodes */
3966 LY_TREE_FOR_SAFE(root.child, next, sub) {
3967 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003970 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003972 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003973 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003974 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003976 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003978 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003979 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003980 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003981 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003982 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003983 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003984 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 goto error;
3986 }
Radek Krejci73adb602015-07-02 18:07:40 +02003987
Michal Vasko345da0a2015-12-02 10:35:55 +01003988 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003991 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003992
3993error:
3994
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003995 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003997 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004001}
4002
Michal Vasko0d343d12015-08-24 14:57:36 +02004003/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004004static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004005read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4006 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004007{
Radek Krejcie0674f82015-06-15 13:58:51 +02004008 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004009 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004010 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004011 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004012 int r;
4013 int c_tpdf = 0;
4014
Radek Krejcie0674f82015-06-15 13:58:51 +02004015 /* init */
4016 memset(&root, 0, sizeof root);
4017
Michal Vasko38d01f72015-06-15 09:41:06 +02004018 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004019 if (!inout) {
4020 LOGMEM;
4021 return NULL;
4022 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004023 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004024
4025 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004026 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004027 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004028 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004029 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004030 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004031 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004032 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004033 }
4034
Radek Krejci76512572015-08-04 09:47:08 +02004035 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004036
Radek Krejci6a113852015-07-03 16:04:20 +02004037 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004038 goto error;
4039 }
4040
Radek Krejcia9544502015-08-14 08:24:29 +02004041 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4042
Michal Vasko38d01f72015-06-15 09:41:06 +02004043 /* data statements */
4044 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004045 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4046 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004047 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004048 continue;
4049 }
4050
Michal Vasko38d01f72015-06-15 09:41:06 +02004051 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004052 !strcmp(sub->name, "leaf-list") ||
4053 !strcmp(sub->name, "leaf") ||
4054 !strcmp(sub->name, "list") ||
4055 !strcmp(sub->name, "choice") ||
4056 !strcmp(sub->name, "uses") ||
4057 !strcmp(sub->name, "grouping") ||
4058 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004059 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004060 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004063 } else if (!strcmp(sub->name, "typedef")) {
4064 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004065
Michal Vasko38d01f72015-06-15 09:41:06 +02004066 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004067 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004068 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004069 }
4070 }
4071
4072 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4073 if (c_tpdf) {
4074 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004075 if (!inout->tpdf) {
4076 LOGMEM;
4077 goto error;
4078 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004079 }
4080
Radek Krejci73adb602015-07-02 18:07:40 +02004081 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004082 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4083 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004084 if (r) {
4085 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004086 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004087 }
4088
Michal Vasko4f0dad02016-02-15 14:08:23 +01004089 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004090 goto error;
4091 }
4092
Michal Vasko38d01f72015-06-15 09:41:06 +02004093 /* last part - process data nodes */
4094 LY_TREE_FOR_SAFE(root.child, next, sub) {
4095 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004096 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004097 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004098 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004099 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004100 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004102 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004103 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004104 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004105 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004106 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004107 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004108 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004109 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004110 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004111 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004112 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004113 goto error;
4114 }
Radek Krejci73adb602015-07-02 18:07:40 +02004115
Michal Vasko345da0a2015-12-02 10:35:55 +01004116 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004117 }
4118
Michal Vasko38d01f72015-06-15 09:41:06 +02004119 return retval;
4120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004121error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004122
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004123 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004124 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004125 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004126 }
4127
4128 return NULL;
4129}
4130
Michal Vasko0d343d12015-08-24 14:57:36 +02004131/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004132static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004133read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4134 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004135{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004136 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004137 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004138 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004139 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004140 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004141 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004142
Michal Vaskoc6551b32015-06-16 10:51:43 +02004143 memset(&root, 0, sizeof root);
4144
Michal Vasko0ea41032015-06-16 08:53:55 +02004145 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004146 if (!notif) {
4147 LOGMEM;
4148 return NULL;
4149 }
Radek Krejci76512572015-08-04 09:47:08 +02004150 notif->nodetype = LYS_NOTIF;
4151 notif->prev = (struct lys_node *)notif;
4152 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004153
Radek Krejci6a113852015-07-03 16:04:20 +02004154 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004155 goto error;
4156 }
4157
Radek Krejcia9544502015-08-14 08:24:29 +02004158 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4159
Michal Vasko0ea41032015-06-16 08:53:55 +02004160 /* process rpc's specific children */
4161 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004162 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4163 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004164 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004165 continue;
4166 }
4167
Michal Vasko0ea41032015-06-16 08:53:55 +02004168 /* data statements */
4169 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004170 !strcmp(sub->name, "leaf-list") ||
4171 !strcmp(sub->name, "leaf") ||
4172 !strcmp(sub->name, "list") ||
4173 !strcmp(sub->name, "choice") ||
4174 !strcmp(sub->name, "uses") ||
4175 !strcmp(sub->name, "grouping") ||
4176 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004177 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004178 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004181 } else if (!strcmp(sub->name, "typedef")) {
4182 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004183 } else if (!strcmp(sub->name, "if-feature")) {
4184 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004185 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004186 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004187 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004188 }
4189 }
4190
4191 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4192 if (c_tpdf) {
4193 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004194 if (!notif->tpdf) {
4195 LOGMEM;
4196 goto error;
4197 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004198 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004199 if (c_ftrs) {
4200 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004201 if (!notif->features) {
4202 LOGMEM;
4203 goto error;
4204 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004205 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004206
Radek Krejci73adb602015-07-02 18:07:40 +02004207 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004208 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004209 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4210 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004211 if (r) {
4212 goto error;
4213 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004214 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004215 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004216 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004217 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004218 goto error;
4219 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004220 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004221 }
4222
Michal Vasko4f0dad02016-02-15 14:08:23 +01004223 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004224 goto error;
4225 }
4226
Michal Vasko0ea41032015-06-16 08:53:55 +02004227 /* last part - process data nodes */
4228 LY_TREE_FOR_SAFE(root.child, next, sub) {
4229 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004230 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004231 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004232 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004233 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004234 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004235 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004236 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004237 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004238 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004239 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004240 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004241 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004242 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004243 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004244 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004245 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004246 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004247 goto error;
4248 }
Radek Krejci73adb602015-07-02 18:07:40 +02004249
Michal Vasko345da0a2015-12-02 10:35:55 +01004250 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004251 }
4252
Michal Vasko0ea41032015-06-16 08:53:55 +02004253 return retval;
4254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004256
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004257 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004258 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004259 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004260 }
4261
4262 return NULL;
4263}
4264
Michal Vasko0d343d12015-08-24 14:57:36 +02004265/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004266static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004267read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4268 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004269{
Radek Krejcie0674f82015-06-15 13:58:51 +02004270 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004271 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004272 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004273 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004274 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004275 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004276
Radek Krejcie0674f82015-06-15 13:58:51 +02004277 /* init */
4278 memset(&root, 0, sizeof root);
4279
Michal Vasko38d01f72015-06-15 09:41:06 +02004280 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004281 if (!rpc) {
4282 LOGMEM;
4283 return NULL;
4284 }
Radek Krejci76512572015-08-04 09:47:08 +02004285 rpc->nodetype = LYS_RPC;
4286 rpc->prev = (struct lys_node *)rpc;
4287 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004288
Radek Krejci6a113852015-07-03 16:04:20 +02004289 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004290 goto error;
4291 }
4292
Radek Krejcia9544502015-08-14 08:24:29 +02004293 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4294
Michal Vasko38d01f72015-06-15 09:41:06 +02004295 /* process rpc's specific children */
4296 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004297 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4298 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004299 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004300 continue;
4301 }
4302
Michal Vasko38d01f72015-06-15 09:41:06 +02004303 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004304 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004305 && (rpc->child->nodetype == LYS_INPUT
4306 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004307 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004308 goto error;
4309 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004310 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004311 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004312 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004314 && (rpc->child->nodetype == LYS_INPUT
4315 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004316 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004317 goto error;
4318 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004319 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004320 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004322 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004323 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004324 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004325 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004327 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004328 } else if (!strcmp(sub->name, "typedef")) {
4329 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004330 } else if (!strcmp(sub->name, "if-feature")) {
4331 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004332 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004333 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004334 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004335 }
4336 }
4337
4338 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4339 if (c_tpdf) {
4340 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004341 if (!rpc->tpdf) {
4342 LOGMEM;
4343 goto error;
4344 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004345 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004346 if (c_ftrs) {
4347 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004348 if (!rpc->features) {
4349 LOGMEM;
4350 goto error;
4351 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004352 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004353
Radek Krejci73adb602015-07-02 18:07:40 +02004354 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004355 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004356 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4357 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004358 if (r) {
4359 goto error;
4360 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004361 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004362 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004363 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004364 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004365 goto error;
4366 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004367 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004368 }
4369
Michal Vasko4f0dad02016-02-15 14:08:23 +01004370 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004371 goto error;
4372 }
4373
Michal Vasko38d01f72015-06-15 09:41:06 +02004374 /* last part - process data nodes */
4375 LY_TREE_FOR_SAFE(root.child, next, sub) {
4376 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004377 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004378 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004379 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004380 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004381 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004382 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004383 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004384 goto error;
4385 }
Radek Krejci73adb602015-07-02 18:07:40 +02004386
Michal Vasko345da0a2015-12-02 10:35:55 +01004387 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004388 }
4389
Michal Vasko38d01f72015-06-15 09:41:06 +02004390 return retval;
4391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004392error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004393
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004394 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004395 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004396 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004397 }
4398
4399 return NULL;
4400}
4401
Michal Vasko0d343d12015-08-24 14:57:36 +02004402/* logs directly
4403 *
Radek Krejci74705112015-06-05 10:25:44 +02004404 * resolve - referenced grouping should be bounded to the namespace (resolved)
4405 * only when uses does not appear in grouping. In a case of grouping's uses,
4406 * we just get information but we do not apply augment or refine to it.
4407 */
Radek Krejci76512572015-08-04 09:47:08 +02004408static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004409read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004410 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004411{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004412 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004413 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004414 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004416 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004417 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004420 if (!uses) {
4421 LOGMEM;
4422 return NULL;
4423 }
Radek Krejci76512572015-08-04 09:47:08 +02004424 uses->nodetype = LYS_USES;
4425 uses->prev = (struct lys_node *)uses;
4426 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004427
Radek Krejcia9544502015-08-14 08:24:29 +02004428 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004430
Michal Vaskoe0c59842015-09-24 13:52:20 +02004431 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4432 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 goto error;
4434 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004435
Radek Krejcia9544502015-08-14 08:24:29 +02004436 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004439 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004440 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4441 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004442 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004443 continue;
4444 }
4445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 if (!strcmp(sub->name, "refine")) {
4447 c_ref++;
4448 } else if (!strcmp(sub->name, "augment")) {
4449 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004450 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004451 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004452 } else if (!strcmp(sub->name, "when")) {
4453 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004454 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004455 goto error;
4456 }
4457
4458 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004459 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004460 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004461 goto error;
4462 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004463 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004465 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 }
4468 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 /* process properties with cardinality 0..n */
4471 if (c_ref) {
4472 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004473 if (!uses->refine) {
4474 LOGMEM;
4475 goto error;
4476 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004477 }
4478 if (c_aug) {
4479 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004480 if (!uses->augment) {
4481 LOGMEM;
4482 goto error;
4483 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004485 if (c_ftrs) {
4486 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004487 if (!uses->features) {
4488 LOGMEM;
4489 goto error;
4490 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004491 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004492
Michal Vasko4f0dad02016-02-15 14:08:23 +01004493 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004494 goto error;
4495 }
4496
Radek Krejcia9544502015-08-14 08:24:29 +02004497 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004498 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004499 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4500 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004501 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004502 goto error;
4503 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004504 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004505 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4506 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004507 if (r) {
4508 goto error;
4509 }
4510 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004511 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004512 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004513 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004514 goto error;
4515 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 }
4517 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004518
Radek Krejci48464ed2016-03-17 15:44:09 +01004519 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004520 goto error;
4521 }
Radek Krejci74705112015-06-05 10:25:44 +02004522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 if (resolve) {
4524 /* inherit config flag */
4525 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004526 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 } else {
4528 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004529 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 }
4531 }
Radek Krejcib388c152015-06-04 17:03:03 +02004532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004534
4535error:
4536
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004537 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004539 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004540}
4541
Michal Vasko0d343d12015-08-24 14:57:36 +02004542/* logs directly
4543 *
4544 * common code for yin_read_module() and yin_read_submodule()
4545 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546static int
Radek Krejcic071c542016-01-27 14:57:51 +01004547read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4548 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004549{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004551 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004552 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004553 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004554 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004556 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01004557 int inc_size_aux = 0;
4558 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004559 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004560 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 +02004561
Radek Krejcic071c542016-01-27 14:57:51 +01004562 /* to simplify code, store the module/submodule being processed as trg */
4563 trg = submodule ? (struct lys_module*)submodule : module;
4564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004565 /* init */
4566 memset(&root, 0, sizeof root);
4567 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004568 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 /*
4571 * in the first run, we process elements with cardinality of 1 or 0..1 and
4572 * count elements with cardinality 0..n. Data elements (choices, containers,
4573 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4574 * need have all top-level and groupings already prepared at that time. In
4575 * the middle loop, we process other elements with carinality of 0..n since
4576 * we need to allocate arrays to store them.
4577 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004578 LY_TREE_FOR_SAFE(yin->child, next, child) {
4579 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004580 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004581 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 continue;
4583 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004584
Radek Krejcic071c542016-01-27 14:57:51 +01004585 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004587 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 goto error;
4589 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004590 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004592 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004593 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004595 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 goto error;
4597 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004598 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004599 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 goto error;
4601 }
4602 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004603 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004604 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4605 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004606 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 goto error;
4608 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004609 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004610 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004611 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 goto error;
4613 }
Radek Krejcif3886932015-06-04 17:36:06 +02004614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004616 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004617 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004620 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004622 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004623 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 goto error;
4625 }
4626 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 /* check here differs from a generic prefix check, since this prefix
4629 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004630 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004631 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 goto error;
4633 }
Radek Krejcic071c542016-01-27 14:57:51 +01004634 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004637 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004638
4639 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004640 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004642 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004644 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004646 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004648 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004650 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004651 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004652 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004653 lyxml_unlink_elem(ctx, child, 2);
4654 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004655
Radek Krejci1d82ef62015-08-07 14:44:40 +02004656 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004657 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004658 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004659 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004662 } else if (!strcmp(child->name, "container") ||
4663 !strcmp(child->name, "leaf-list") ||
4664 !strcmp(child->name, "leaf") ||
4665 !strcmp(child->name, "list") ||
4666 !strcmp(child->name, "choice") ||
4667 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004668 !strcmp(child->name, "anyxml") ||
4669 !strcmp(child->name, "rpc") ||
4670 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004671 lyxml_unlink_elem(ctx, child, 2);
4672 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004673
Radek Krejci1d82ef62015-08-07 14:44:40 +02004674 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004675 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004676 lyxml_unlink_elem(ctx, child, 2);
4677 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004681 if (trg->dsc) {
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->dsc = 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->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 goto error;
4689 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004691 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004692 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004693 goto error;
4694 }
Radek Krejcic071c542016-01-27 14:57:51 +01004695 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004696 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004697 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 goto error;
4699 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004700 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004701 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004702 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004703 goto error;
4704 }
Radek Krejcic071c542016-01-27 14:57:51 +01004705 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004706 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004707 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 goto error;
4709 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004710 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004711 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004712 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 goto error;
4714 }
Radek Krejcic071c542016-01-27 14:57:51 +01004715 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004716 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004717 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 goto error;
4719 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004720 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004722 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004723 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 goto error;
4725 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004726 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 if (strcmp(value, "1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004728 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004729 goto error;
4730 }
Radek Krejcic071c542016-01-27 14:57:51 +01004731 version_flag = 1;
4732 if (!submodule) {
4733 module->version = 1;
4734 } /* 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 +01004735 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004736
Radek Krejci1d82ef62015-08-07 14:44:40 +02004737 } else if (!strcmp(child->name, "extension")) {
4738 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004739
Radek Krejci3d468122015-10-02 13:36:12 +02004740 /* we have the following supported (hardcoded) extensions: */
4741 /* ietf-netconf's get-filter-element-attributes */
4742 if (!strcmp(module->ns, LY_NSNC) &&
4743 !strcmp(value, "get-filter-element-attributes")) {
4744 LOGDBG("NETCONF filter extension found");
4745 /* NACM's default-deny-write and default-deny-all */
4746 } else if (!strcmp(module->ns, LY_NSNACM) &&
4747 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4748 LOGDBG("NACM extension found");
4749 /* other extensions are not supported, so inform about such an extension */
4750 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004751 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004752 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004753 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004755 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 }
4758 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004759
Radek Krejcic071c542016-01-27 14:57:51 +01004760 /* check for mandatory statements */
4761 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004762 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004763 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004764 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004766 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 goto error;
4768 }
4769 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004770 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 goto error;
4772 }
4773 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 /* allocate arrays for elements with cardinality of 0..n */
4776 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004777 trg->imp = calloc(c_imp, sizeof *trg->imp);
4778 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004779 LOGMEM;
4780 goto error;
4781 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 }
4783 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004784 trg->rev = calloc(c_rev, sizeof *trg->rev);
4785 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004786 LOGMEM;
4787 goto error;
4788 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004789 }
4790 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004791 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4792 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004793 LOGMEM;
4794 goto error;
4795 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004796 }
4797 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004798 trg->ident = calloc(c_ident, sizeof *trg->ident);
4799 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004800 LOGMEM;
4801 goto error;
4802 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004803 }
4804 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004805 trg->inc = calloc(c_inc, sizeof *trg->inc);
4806 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004807 LOGMEM;
4808 goto error;
4809 }
Radek Krejcic071c542016-01-27 14:57:51 +01004810 trg->inc_size = c_inc;
4811 /* trg->inc_size can be updated by the included submodules,
4812 * so we will use inc_size_aux here, trg->inc_size stores the
4813 * target size of the array
4814 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004816 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004817 trg->augment = calloc(c_aug, sizeof *trg->augment);
4818 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004819 LOGMEM;
4820 goto error;
4821 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004822 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004823 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004824 trg->features = calloc(c_ftrs, sizeof *trg->features);
4825 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004826 LOGMEM;
4827 goto error;
4828 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004829 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004830 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004831 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4832 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004833 LOGMEM;
4834 goto error;
4835 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004836 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004837
Michal Vasko2f7925f2015-10-21 15:06:56 +02004838 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4839 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004840 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004841 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4842 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004843 if (r) {
4844 goto error;
4845 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004848 for (i = 0; i < trg->imp_size - 1; i++) {
4849 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004850 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->imp[i].module->name, "import");
4851 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 goto error;
4853 }
4854 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004855
Radek Krejci1d82ef62015-08-07 14:44:40 +02004856 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004857 memset(&inc, 0, sizeof inc);
4858 /* 1) pass module, not trg, since we want to pass the main module
4859 * 2) we cannot pass directly the structure in the array since
4860 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004861 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004862 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4863 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004864 if (r) {
4865 goto error;
4866 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004869 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004870 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 +01004871 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
4872 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01004873 trg->inc[inc_size_aux - 1].submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 goto error;
4875 }
4876 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004877
Radek Krejci1d82ef62015-08-07 14:44:40 +02004878 } else if (!strcmp(child->name, "revision")) {
4879 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004880 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 goto error;
4882 }
Radek Krejcic071c542016-01-27 14:57:51 +01004883 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004884 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004885 for (i = 0; i < trg->rev_size; i++) {
4886 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004887 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4888 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 }
4890 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004891
Radek Krejci1d82ef62015-08-07 14:44:40 +02004892 LY_TREE_FOR(child->child, child2) {
4893 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004894 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004895 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 goto error;
4897 }
Radek Krejcic071c542016-01-27 14:57:51 +01004898 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4899 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004900 goto error;
4901 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004902 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004903 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004904 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 goto error;
4906 }
Radek Krejcic071c542016-01-27 14:57:51 +01004907 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4908 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 goto error;
4910 }
4911 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004912 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004913 goto error;
4914 }
4915 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004918 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004920 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004921 if (!value) {
4922 LOGMEM;
4923 goto error;
4924 }
Radek Krejcic071c542016-01-27 14:57:51 +01004925 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4926 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004927 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004928
Radek Krejci749190d2016-02-18 16:26:25 +01004929 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004930 value = trg->rev[0].dsc;
4931 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4932 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004934
Radek Krejci749190d2016-02-18 16:26:25 +01004935 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004936 value = trg->rev[0].ref;
4937 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4938 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004939 }
4940 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004941
Radek Krejcic071c542016-01-27 14:57:51 +01004942 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004943
Radek Krejci1d82ef62015-08-07 14:44:40 +02004944 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004945 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4946 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 if (r) {
4948 goto error;
4949 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004950
Radek Krejci1d82ef62015-08-07 14:44:40 +02004951 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004952 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4953 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004954 if (r) {
4955 goto error;
4956 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004957
Radek Krejci1d82ef62015-08-07 14:44:40 +02004958 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004959 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4960 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004961 if (r) {
4962 goto error;
4963 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004964
Radek Krejci1d82ef62015-08-07 14:44:40 +02004965 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004966 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4967 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004968 if (r) {
4969 goto error;
4970 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004971 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4972 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004976
Pavol Vicane994fda2016-03-22 10:47:58 +01004977 if (submodule && lyp_propagate_submodule(module, submodule)) {
Pavol Vicanaa1eba92016-03-09 12:27:11 +01004978 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004979 }
4980
Radek Krejcif5be10f2015-06-16 13:29:36 +02004981 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004982 * refer to them. Submodule's data nodes are stored in the
4983 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004984 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004985 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004986 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004987 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 goto error;
4989 }
Radek Krejci74705112015-06-05 10:25:44 +02004990
Michal Vasko345da0a2015-12-02 10:35:55 +01004991 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 }
Radek Krejci74705112015-06-05 10:25:44 +02004993
Radek Krejcif5be10f2015-06-16 13:29:36 +02004994 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004995 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004996
Radek Krejci1d82ef62015-08-07 14:44:40 +02004997 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004998 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004999 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005000 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005001 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005002 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005003 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005004 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005005 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005006 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005007 } else if (!strcmp(child->name, "uses")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005008 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005009 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005010 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005011 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005012 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005013 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005014 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005015 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005016 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 goto error;
5018 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005019
Michal Vasko345da0a2015-12-02 10:35:55 +01005020 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005022
Michal Vasko2f7925f2015-10-21 15:06:56 +02005023 /* ... and finally augments (last, so we can augment our data, for instance) */
5024 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005025 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5026 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005027
Michal Vasko2f7925f2015-10-21 15:06:56 +02005028 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005029 goto error;
5030 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005031 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005032 }
5033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005034 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005035
5036error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 /* cleanup */
5038 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005039 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005040 }
5041 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005042 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005043 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005044 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005045 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005046 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005048 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005049}
5050
Michal Vasko0d343d12015-08-24 14:57:36 +02005051/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005052struct lys_submodule *
5053yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005054{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005056 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005057 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005058
Michal Vasko5a721fd2016-02-16 12:16:48 +01005059 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005060
Radek Krejci722b0072016-02-01 17:09:45 +01005061 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005062 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005063 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005064 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005066 /* check root element */
5067 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005068 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005069 goto error;
5070 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005072 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005073 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005074 goto error;
5075 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005076
Michal Vasko5a721fd2016-02-16 12:16:48 +01005077 submodule = calloc(1, sizeof *submodule);
5078 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005079 LOGMEM;
5080 goto error;
5081 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005082
Michal Vasko5a721fd2016-02-16 12:16:48 +01005083 submodule->ctx = module->ctx;
5084 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5085 submodule->type = 1;
5086 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005087
Michal Vasko5a721fd2016-02-16 12:16:48 +01005088 LOGVRB("Reading submodule \"%s\".", submodule->name);
5089 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005090 goto error;
5091 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005093 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005094 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005095
Michal Vasko5a721fd2016-02-16 12:16:48 +01005096 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005097
Michal Vasko5a721fd2016-02-16 12:16:48 +01005098 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005099
5100error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005101 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005102 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005103 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005104
Michal Vasko5a721fd2016-02-16 12:16:48 +01005105 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005106 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005107 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005108 }
5109
Michal Vasko5a721fd2016-02-16 12:16:48 +01005110 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005111
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005112 lyp_fail_submodule(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005113 lys_submodule_free(submodule, NULL);
5114
5115 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005116}
5117
Michal Vasko0d343d12015-08-24 14:57:36 +02005118/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005119struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005120yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005121{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005122 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005123 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005124 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005125 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005126
Radek Krejcic071c542016-01-27 14:57:51 +01005127 unres = calloc(1, sizeof *unres);
5128 if (!unres) {
5129 LOGMEM;
5130 return NULL;
5131 }
5132
Radek Krejci722b0072016-02-01 17:09:45 +01005133 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005135 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005136 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 /* check root element */
5139 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005140 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005141 goto error;
5142 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005144 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005145 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005146 goto error;
5147 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005149 module = calloc(1, sizeof *module);
5150 if (!module) {
5151 LOGMEM;
5152 goto error;
5153 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005155 module->ctx = ctx;
5156 module->name = lydict_insert(ctx, value, strlen(value));
5157 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005158 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005159
Michal Vasko9f258e42016-02-11 11:36:27 +01005160 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005161 if (read_sub_module(module, NULL, yin, unres)) {
5162 goto error;
5163 }
5164
5165 /* resolve rest of unres items */
5166 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 goto error;
5168 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005169
Radek Krejciff4874d2016-03-07 12:30:50 +01005170 if (revision) {
5171 /* check revision of the parsed model */
5172 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005173 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5174 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005175 goto error;
5176 }
5177 }
5178
Radek Krejci5deaafd2016-03-30 13:27:47 +02005179 if (lyp_add_module(&module, implement)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005180 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005184 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005185 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005186
Michal Vasko9f258e42016-02-11 11:36:27 +01005187 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005189 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005190
5191error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005192 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005193 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005194 unres_schema_free(module, &unres);
5195
5196 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005197 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005198 return NULL;
5199 }
5200
5201 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005202
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005203 lyp_fail_module(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005204 lys_free(module, NULL, 1);
5205
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005206 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005207}