blob: cfc51838e83d1907ad7348bcff172a399fd64b10 [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 }
Radek Krejcic4283442016-04-22 09:19:27 +02001269 if (dev_target->module == lys_main_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 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001274 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001275
1276 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001277 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1278 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001279 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001280 continue;
1281 }
1282
Radek Krejcieb00f512015-07-01 16:44:58 +02001283 if (!strcmp(child->name, "description")) {
1284 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001285 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001286 goto error;
1287 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001288 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001289 if (!dev->dsc) {
1290 goto error;
1291 }
1292 } else if (!strcmp(child->name, "reference")) {
1293 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001294 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001295 goto error;
1296 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001297 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001298 if (!dev->ref) {
1299 goto error;
1300 }
1301 } else if (!strcmp(child->name, "deviate")) {
1302 c_dev++;
1303
Michal Vasko345da0a2015-12-02 10:35:55 +01001304 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001305 * further processed later
1306 */
1307 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001308
Radek Krejcieb00f512015-07-01 16:44:58 +02001309 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001310 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001311 goto error;
1312 }
1313
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001314 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001315 }
1316
1317 if (c_dev) {
1318 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001319 if (!dev->deviate) {
1320 LOGMEM;
1321 goto error;
1322 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001323 }
1324
1325 LY_TREE_FOR(yin->child, develem) {
1326 /* init */
1327 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001328 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001329 c_must = 0;
1330 c_uniq = 0;
1331
1332 /* get deviation type */
1333 GETVAL(value, develem, "value");
1334 if (!strcmp(value, "not-supported")) {
1335 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1336 /* no property expected in this case */
1337 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001338 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001339 goto error;
1340 }
1341
Radek Krejci5b917642015-07-02 09:03:13 +02001342 /* and neither any other deviate statement is expected,
1343 * not-supported deviation must be the only deviation of the target
1344 */
1345 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001346 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1347 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001348 goto error;
1349 }
1350
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001351 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001352 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1353 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1354 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001355 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1356 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001357 goto error;
1358 }
1359 }
1360 }
Radek Krejci5b917642015-07-02 09:03:13 +02001361
Michal Vaskoff006c12016-02-17 11:15:19 +01001362 /* unlink and store the original node */
1363 lys_node_unlink(dev_target);
1364 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001365
Radek Krejci5b917642015-07-02 09:03:13 +02001366 dev->deviate_size = 1;
1367 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001368 } else if (!strcmp(value, "add")) {
1369 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1370 } else if (!strcmp(value, "replace")) {
1371 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1372 } else if (!strcmp(value, "delete")) {
1373 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1374 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001375 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001376 goto error;
1377 }
1378 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001379 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001380
Michal Vaskoff006c12016-02-17 11:15:19 +01001381 /* store a shallow copy of the original node */
1382 if (!dev->orig_node) {
1383 memset(&tmp_unres, 0, sizeof tmp_unres);
1384 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1385 /* just to be safe */
1386 if (tmp_unres.count) {
1387 LOGINT;
1388 goto error;
1389 }
1390 }
1391
Radek Krejcieb00f512015-07-01 16:44:58 +02001392 /* process deviation properties */
1393 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001394 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1395 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001396 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001397 continue;
1398 }
1399
Radek Krejcieb00f512015-07-01 16:44:58 +02001400 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001401 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001402 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001403 goto error;
1404 }
1405
1406 /* for we deviate from RFC 6020 and allow config property even it is/is not
1407 * specified in the target explicitly since config property inherits. So we expect
1408 * that config is specified in every node. But for delete, we check that the value
1409 * is the same as here in deviation
1410 */
1411 GETVAL(value, child, "value");
1412 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001413 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001414 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001415 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001416 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001417 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 goto error;
1419 }
1420
1421 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001422 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001423 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001424 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001425 } else { /* add and replace are the same in this case */
1426 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001427 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001428
1429 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001430 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001431 }
1432 } else if (!strcmp(child->name, "default")) {
1433 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 goto error;
1436 }
1437 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001438 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001439
Michal Vasko60f4b452016-02-12 11:02:55 +01001440 if (dev_target->nodetype == LYS_CHOICE) {
1441 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001442
1443 if (d->mod == LY_DEVIATE_ADD) {
1444 /* check that there is no current value */
1445 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001446 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1447 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001448 goto error;
1449 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001450 /* check collision with mandatory */
1451 if (choice->flags & LYS_MAND_TRUE) {
1452 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1453 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1454 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1455 goto error;
1456 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001457 } else if (d->mod == LY_DEVIATE_RPL) {
1458 /* check that there was a value before */
1459 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001460 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1461 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001462 goto error;
1463 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001464 }
1465
Michal Vasko3edeaf72016-02-11 13:17:43 +01001466 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001467 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001468 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001469 goto error;
1470 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001472 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001473 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1474 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001475 goto error;
1476 }
1477 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001478 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001479 if (!choice->dflt) {
1480 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001481 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001482 goto error;
1483 }
1484 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001485 } else if (dev_target->nodetype == LYS_LEAF) {
1486 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001487
1488 if (d->mod == LY_DEVIATE_ADD) {
1489 /* check that there is no current value */
1490 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001491 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1492 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001493 goto error;
1494 }
Radek Krejci841ec082016-04-05 13:05:17 +02001495 /* check collision with mandatory */
1496 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001497 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001498 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001499 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001500 goto error;
1501 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 }
1503
1504 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001505 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001506 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1507 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001508 goto error;
1509 }
1510 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001511 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 leaf->dflt = NULL;
1513 } else { /* add (already checked) and replace */
1514 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001515 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001516
1517 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001518 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001519
1520 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1521 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1522 if (!leaf_dflt_check) {
1523 LOGMEM;
1524 goto error;
1525 }
1526 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001527 }
1528 } else {
1529 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001530 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1531 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 goto error;
1533 }
1534 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001535 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001536 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001537 goto error;
1538 }
1539
1540 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001541 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001542 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1543 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 goto error;
1545 }
1546
1547 GETVAL(value, child, "value");
1548 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001549 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001551 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001552 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001553 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 goto error;
1555 }
1556
1557 if (d->mod == LY_DEVIATE_ADD) {
1558 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001559 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001560 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1561 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 goto error;
1563 }
Radek Krejci841ec082016-04-05 13:05:17 +02001564 /* check collision with default-stmt */
1565 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001566 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001568 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001569 goto error;
1570 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001571
Michal Vasko21be1b32016-03-07 12:31:34 +01001572 dev_target->flags |= d->flags & LYS_MAND_MASK;
1573 } else if (d->mod == LY_DEVIATE_RPL) {
1574 /* check that there was a value before */
1575 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001576 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1577 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001578 goto error;
1579 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001580
Michal Vasko21be1b32016-03-07 12:31:34 +01001581 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001582 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001583 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001584 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001585 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001586 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 }
1588 } else if (!strcmp(child->name, "min-elements")) {
1589 if (f_min) {
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 f_min = 1;
1594
Michal Vasko60f4b452016-02-12 11:02:55 +01001595 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001596 goto error;
1597 }
1598 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001599 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001600 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001601 goto error;
1602 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001603 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001604
Michal Vasko60f4b452016-02-12 11:02:55 +01001605 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 goto error;
1607 }
1608 } else if (!strcmp(child->name, "must")) {
1609 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001610 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001611 continue;
1612 } else if (!strcmp(child->name, "type")) {
1613 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001614 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001615 goto error;
1616 }
1617
Michal Vaskof7e57d52016-03-07 11:31:09 +01001618 /* add, del type is forbidden */
1619 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001620 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001621 goto error;
1622 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001623 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001624 goto error;
1625 }
1626
Radek Krejcieb00f512015-07-01 16:44:58 +02001627 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001628 if (dev_target->nodetype == LYS_LEAF) {
1629 t = &((struct lys_node_leaf *)dev_target)->type;
1630 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1631 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001632 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001633 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1634 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 goto error;
1636 }
1637
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001639 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001640 /* HACK for unres */
1641 t->der = (struct lys_tpdf *)child;
Radek Krejci48464ed2016-03-17 15:44:09 +01001642 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001643 goto error;
1644 }
1645 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001646
1647 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1648 if (dev_target->nodetype == LYS_LEAF) {
1649 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1650 if (!leaf_dflt_check) {
1651 LOGMEM;
1652 goto error;
1653 }
1654 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1655 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001656 } else if (!strcmp(child->name, "unique")) {
1657 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001658 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001659 continue;
1660 } else if (!strcmp(child->name, "units")) {
1661 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001662 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001663 goto error;
1664 }
1665
1666 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001667 if (dev_target->nodetype == LYS_LEAFLIST) {
1668 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1669 } else if (dev_target->nodetype == LYS_LEAF) {
1670 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001672 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1673 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001674 goto error;
1675 }
1676
1677 /* get units value */
1678 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001679 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001680
1681 /* apply to target */
1682 if (d->mod == LY_DEVIATE_ADD) {
1683 /* check that there is no current value */
1684 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001685 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1686 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001687 goto error;
1688 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001689
Michal Vasko21be1b32016-03-07 12:31:34 +01001690 *stritem = lydict_insert(ctx, value, 0);
1691 } else if (d->mod == LY_DEVIATE_RPL) {
1692 /* check that there was a value before */
1693 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001694 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1695 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001696 goto error;
1697 }
1698
1699 lydict_remove(ctx, *stritem);
1700 *stritem = lydict_insert(ctx, value, 0);
1701 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001702 /* check values */
1703 if (*stritem != d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001704 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1705 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001706 goto error;
1707 }
1708 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001709 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001710 }
1711 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001712 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 goto error;
1714 }
1715
Michal Vasko88c29542015-11-27 14:57:53 +01001716 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001717 }
1718
1719 if (c_must) {
1720 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001721 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001722 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001723 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1724 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 break;
Radek Krejci76512572015-08-04 09:47:08 +02001726 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001727 trg_must = &((struct lys_node_container *)dev_target)->must;
1728 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 break;
Radek Krejci76512572015-08-04 09:47:08 +02001730 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001731 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1732 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001733 break;
Radek Krejci76512572015-08-04 09:47:08 +02001734 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001735 trg_must = &((struct lys_node_list *)dev_target)->must;
1736 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001737 break;
Radek Krejci76512572015-08-04 09:47:08 +02001738 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001739 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1740 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 break;
1742 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001743 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1744 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001745 goto error;
1746 }
1747
1748 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001749 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001750 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001751 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001752 } else if (d->mod == LY_DEVIATE_ADD) {
1753 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001754 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001755 if (!d->must) {
1756 LOGMEM;
1757 goto error;
1758 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001759 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001760 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 d->must_size = c_must;
1762 } else { /* LY_DEVIATE_DEL */
1763 d->must = calloc(c_must, sizeof *d->must);
1764 }
Michal Vasko253035f2015-12-17 16:58:13 +01001765 if (!d->must) {
1766 LOGMEM;
1767 goto error;
1768 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001769 }
1770 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001771 /* replace unique is forbidden */
1772 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001773 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001774 goto error;
1775 }
1776
Radek Krejcieb00f512015-07-01 16:44:58 +02001777 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001778 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001779 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1780 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001781 goto error;
1782 }
1783
Michal Vasko60f4b452016-02-12 11:02:55 +01001784 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001785 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001786 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001787 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 list->unique = d->unique;
1789 d->unique = &list->unique[list->unique_size];
1790 d->unique_size = c_uniq;
1791 } else { /* LY_DEVIATE_DEL */
1792 d->unique = calloc(c_uniq, sizeof *d->unique);
1793 }
Michal Vasko253035f2015-12-17 16:58:13 +01001794 if (!d->unique) {
1795 LOGMEM;
1796 goto error;
1797 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 }
1799
1800 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001801 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001802 if (!strcmp(child->name, "must")) {
1803 if (d->mod == LY_DEVIATE_DEL) {
1804 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1805 goto error;
1806 }
1807
1808 /* find must to delete, we are ok with just matching conditions */
1809 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001810 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001812 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001813 /* ... and maintain the array */
1814 (*trg_must_size)--;
1815 if (i != *trg_must_size) {
1816 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1817 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1818 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1819 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1820 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1821 }
1822 if (!(*trg_must_size)) {
1823 free(*trg_must);
1824 *trg_must = NULL;
1825 } else {
1826 (*trg_must)[*trg_must_size].expr = NULL;
1827 (*trg_must)[*trg_must_size].dsc = NULL;
1828 (*trg_must)[*trg_must_size].ref = NULL;
1829 (*trg_must)[*trg_must_size].eapptag = NULL;
1830 (*trg_must)[*trg_must_size].emsg = NULL;
1831 }
1832
1833 i = -1; /* set match flag */
1834 break;
1835 }
1836 }
1837 d->must_size++;
1838 if (i != -1) {
1839 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001840 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001841 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001842 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001843 goto error;
1844 }
1845 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001846 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1847 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001848 goto error;
1849 }
1850 (*trg_must_size)++;
1851 }
1852 } else if (!strcmp(child->name, "unique")) {
1853 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001854 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001855 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001856 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 goto error;
1858 }
1859
1860 /* find unique structures to delete */
1861 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001862 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001863 continue;
1864 }
1865
Radek Krejci581ce772015-11-10 17:22:40 +01001866 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001867 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001868 break;
1869 }
1870 }
1871
Radek Krejci581ce772015-11-10 17:22:40 +01001872 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001873 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001874 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001875 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001876 }
1877 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001878 /* ... and maintain the array */
1879 list->unique_size--;
1880 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001881 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1882 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001883 }
1884
1885 if (!list->unique_size) {
1886 free(list->unique);
1887 list->unique = NULL;
1888 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001889 list->unique[list->unique_size].expr_size = 0;
1890 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001891 }
1892
1893 i = -1; /* set match flag */
1894 break;
1895 }
1896 }
1897
1898 d->unique_size++;
1899 if (i != -1) {
1900 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001901 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1902 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001903 goto error;
1904 }
1905 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001906 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001907 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001908 list->unique_size++;
1909 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 goto error;
1911 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001912 }
1913 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001914 }
1915 }
1916
Michal Vasko43a1feb2016-03-07 12:03:02 +01001917 /* now check whether default value, if any, matches the type */
1918 for (i = 0; i < leaf_dflt_check_count; ++i) {
1919 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001920 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 +01001921 if (rc == -1) {
1922 goto error;
1923 } else if (rc == EXIT_FAILURE) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001924 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1925 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 +01001926 goto error;
1927 }
1928 }
1929 }
1930 free(leaf_dflt_check);
1931
Radek Krejcieb00f512015-07-01 16:44:58 +02001932 return EXIT_SUCCESS;
1933
1934error:
Michal Vasko34867132016-03-11 10:26:38 +01001935 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001936 return EXIT_FAILURE;
1937}
1938
Michal Vasko0d343d12015-08-24 14:57:36 +02001939/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001940static int
Radek Krejcib8048692015-08-05 13:36:34 +02001941fill_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 +02001942 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001943{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001945 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001946 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001947 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001948
Michal Vasko591e0b22015-08-13 13:53:43 +02001949 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001950 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001951 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02001952 if (!aug->target_name) {
1953 goto error;
1954 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001956
Michal Vasko1d87a922015-08-21 12:57:16 +02001957 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001958 goto error;
1959 }
1960
1961 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001962 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1963 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001964 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001965 continue;
1966 }
1967
Radek Krejci3cf9e222015-06-18 11:37:50 +02001968 if (!strcmp(child->name, "if-feature")) {
1969 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001970 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001971 } else if (!strcmp(child->name, "when")) {
1972 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001973 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001974 goto error;
1975 }
1976
1977 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001978 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001979 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001980 goto error;
1981 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001982 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001983 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001984
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001985 /* check allowed data sub-statements */
1986 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001987 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001988 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001989 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001990 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001991 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001992 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001993 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001995 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001996 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001997 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001998 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001999 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002000 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002003 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002004 goto error;
2005 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006
Radek Krejci1d82ef62015-08-07 14:44:40 +02002007 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 goto error;
2009 }
2010
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002012 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002013 }
2014
2015 if (c) {
2016 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002017 if (!aug->features) {
2018 LOGMEM;
2019 goto error;
2020 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002021 }
2022
2023 LY_TREE_FOR_SAFE(yin->child, next, child) {
2024 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002025 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002026 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002027 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002028 goto error;
2029 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002030 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002031 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002032 }
2033
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002034 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002035 * connected to the tree and adjusted (if possible right now).
2036 * However, if this is augment in a uses, it gets resolved
2037 * when the uses does and cannot be resolved now for sure
2038 * (the grouping was not yet copied into uses).
2039 */
2040 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002041 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002042 goto error;
2043 }
Michal Vasko49291b32015-08-06 09:49:41 +02002044 }
Radek Krejci106efc02015-06-10 14:36:27 +02002045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002047
2048error:
2049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002050 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002051}
2052
Michal Vasko0d343d12015-08-24 14:57:36 +02002053/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054static int
Michal Vasko0d204592015-10-07 09:50:04 +02002055fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002056{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002057 struct lyxml_elem *sub, *next;
2058 const char *value;
2059 char *endptr;
2060 int f_mand = 0, f_min = 0, f_max = 0;
2061 int c_must = 0;
2062 int r;
2063 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002064
Radek Krejci76512572015-08-04 09:47:08 +02002065 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 goto error;
2067 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002068
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002069 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002070 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002071 if (!rfn->target_name) {
2072 goto error;
2073 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002076 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2077 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002078 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002079 continue;
2080 }
2081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 /* limited applicability */
2083 if (!strcmp(sub->name, "default")) {
2084 /* leaf or choice */
2085 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002086 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 goto error;
2088 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 /* check possibility of statements combination */
2091 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002092 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002094 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2095 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 goto error;
2097 }
2098 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002099 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 GETVAL(value, sub, "value");
2103 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2104 } else if (!strcmp(sub->name, "mandatory")) {
2105 /* leaf, choice or anyxml */
2106 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002107 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 goto error;
2109 }
2110 /* just checking the flags in leaf is not sufficient, we would allow
2111 * multiple mandatory statements with the "false" value
2112 */
2113 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 /* check possibility of statements combination */
2116 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002117 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002119 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2120 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 goto error;
2122 }
2123 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002124 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 GETVAL(value, sub, "value");
2128 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002129 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002131 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002133 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 goto error;
2135 }
2136 } else if (!strcmp(sub->name, "min-elements")) {
2137 /* list or leaf-list */
2138 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002139 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 goto error;
2141 }
2142 f_min = 1;
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_LIST | LYS_LEAFLIST);
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_LIST | LYS_LEAFLIST;
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 while (isspace(value[0])) {
2158 value++;
2159 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 /* convert it to uint32_t */
2162 errno = 0;
2163 endptr = NULL;
2164 val = strtoul(value, &endptr, 10);
2165 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002166 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 goto error;
2168 }
2169 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002170 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 } else if (!strcmp(sub->name, "max-elements")) {
2172 /* list or leaf-list */
2173 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002174 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 goto error;
2176 }
2177 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 /* check possibility of statements combination */
2180 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002181 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002183 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2184 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 goto error;
2186 }
2187 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002188 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 GETVAL(value, sub, "value");
2192 while (isspace(value[0])) {
2193 value++;
2194 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002195
Radek Krejci0d7b2472016-02-12 11:11:03 +01002196 if (!strcmp(value, "unbounded")) {
2197 rfn->mod.list.max = 0;
2198 } else {
2199 /* convert it to uint32_t */
2200 errno = 0;
2201 endptr = NULL;
2202 val = strtoul(value, &endptr, 10);
2203 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002204 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002205 goto error;
2206 }
2207 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002209 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 } else if (!strcmp(sub->name, "presence")) {
2211 /* container */
2212 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002213 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 goto error;
2215 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 /* check possibility of statements combination */
2218 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002219 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002221 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2222 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 goto error;
2224 }
2225 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002226 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 GETVAL(value, sub, "value");
2230 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2231 } else if (!strcmp(sub->name, "must")) {
2232 /* leaf-list, list, container or anyxml */
2233 /* 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 | LYS_CONTAINER | LYS_ANYXML);
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 | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002246 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002249 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 goto error;
2251 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002252
Michal Vasko345da0a2015-12-02 10:35:55 +01002253 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 /* process nodes with cardinality of 0..n */
2257 if (c_must) {
2258 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002259 if (!rfn->must) {
2260 LOGMEM;
2261 goto error;
2262 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 }
Radek Krejci73adb602015-07-02 18:07:40 +02002264 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002265 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2266 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002267 if (r) {
2268 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002273
2274error:
2275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002277}
2278
Michal Vasko0d343d12015-08-24 14:57:36 +02002279/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280static int
Radek Krejcib8048692015-08-05 13:36:34 +02002281fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002282{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 struct lyxml_elem *child;
2284 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002287 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2288 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002289 continue;
2290 }
2291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 if (!strcmp(child->name, "prefix")) {
2293 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002294 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 goto error;
2296 }
2297 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2298 } else if (!strcmp(child->name, "revision-date")) {
2299 if (imp->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002300 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 goto error;
2302 }
2303 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002304 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 goto error;
2306 }
2307 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2308 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002309 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 goto error;
2311 }
2312 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 /* check mandatory information */
2315 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002316 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 goto error;
2318 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002321
Pavol Vicane994fda2016-03-22 10:47:58 +01002322 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002323
2324error:
2325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002327}
2328
Michal Vasko0d343d12015-08-24 14:57:36 +02002329/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002331fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2332 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002333{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 struct lyxml_elem *child;
2335 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002338 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2339 /* garbage */
2340 continue;
2341 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 if (!strcmp(child->name, "revision-date")) {
2343 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002344 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002345 goto error;
2346 }
2347 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002348 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 goto error;
2350 }
2351 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2352 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002353 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 goto error;
2355 }
2356 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002359
Pavol Vican0adf01d2016-03-22 12:29:33 +01002360 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002361
2362error:
2363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002365}
2366
Michal Vasko0d343d12015-08-24 14:57:36 +02002367/* logs directly
2368 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002369 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002370 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002371 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002372 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373static int
Radek Krejcib8048692015-08-05 13:36:34 +02002374read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002375 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002376{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 const char *value;
2378 struct lyxml_elem *sub, *next;
2379 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002382 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 if (opt & OPT_IDENT) {
2386 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002387 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002388 goto error;
2389 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002390 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002392
Radek Krejci6764bb32015-07-03 15:16:04 +02002393 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002394 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002395 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002396 }
2397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 /* process local parameters */
2399 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002400 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002401 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002402 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002403 continue;
2404 }
2405 if (strcmp(sub->ns->value, LY_NSYIN)) {
2406 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002407 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002408 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002409 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002410 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002411 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002412 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002413 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002414 goto error;
2415 }
2416 }
2417
2418 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002419 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002420 continue;
2421 }
2422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002424 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002425 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 goto error;
2427 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002428 node->dsc = read_yin_subnode(ctx, sub, "text");
2429 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002430 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 }
2432 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002433 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 goto error;
2436 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002437 node->ref = read_yin_subnode(ctx, sub, "text");
2438 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002439 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002440 }
2441 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002442 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002443 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002444 goto error;
2445 }
2446 GETVAL(value, sub, "value");
2447 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002448 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002450 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002451 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002452 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002454 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002455 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 }
2457 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002458 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002459 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 goto error;
2461 }
2462 GETVAL(value, sub, "value");
2463 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002464 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002466 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002467 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002468 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002469 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002471 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002472 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002473 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002474 continue;
2475 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002476 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002478
Radek Krejci1d82ef62015-08-07 14:44:40 +02002479 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002481 if (parent && (parent->flags & LYS_CONFIG_R)) {
2482 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 } else {
2484 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 }
2487 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002490
2491error:
2492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002494}
2495
Michal Vasko0d343d12015-08-24 14:57:36 +02002496/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002497static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002498read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002499{
Radek Krejci76512572015-08-04 09:47:08 +02002500 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002501 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002502 const char *value;
2503
2504 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002505 if (!retval) {
2506 LOGMEM;
2507 return NULL;
2508 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002509
2510 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002511 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002512 if (!retval->cond) {
2513 goto error;
2514 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002515 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002516 goto error;
2517 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002518
Radek Krejci73adb602015-07-02 18:07:40 +02002519 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002520 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2521 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002522 continue;
2523 }
2524
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002525 if (!strcmp(child->name, "description")) {
2526 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002527 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002528 goto error;
2529 }
2530 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2531 if (!retval->dsc) {
2532 goto error;
2533 }
2534 } else if (!strcmp(child->name, "reference")) {
2535 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002536 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002537 goto error;
2538 }
2539 retval->ref = read_yin_subnode(module->ctx, child, "text");
2540 if (!retval->ref) {
2541 goto error;
2542 }
2543 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002544 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002545 goto error;
2546 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002547 }
2548
2549 return retval;
2550
2551error:
2552
Michal Vasko0308dd62015-10-07 09:14:40 +02002553 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002554 return NULL;
2555}
2556
Michal Vasko0d343d12015-08-24 14:57:36 +02002557/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002558static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002559read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2560 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002561{
Michal Vasko29fc0182015-08-24 15:02:39 +02002562 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002563 struct lys_node_case *cs;
2564 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002565 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002566
Radek Krejcie867c852015-08-27 09:52:34 +02002567 /* init */
2568 memset(&root, 0, sizeof root);
2569
Radek Krejci1d82ef62015-08-07 14:44:40 +02002570 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002571 if (!cs) {
2572 LOGMEM;
2573 return NULL;
2574 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002575 cs->nodetype = LYS_CASE;
2576 cs->prev = (struct lys_node *)cs;
2577 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002578
Radek Krejci6a113852015-07-03 16:04:20 +02002579 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 goto error;
2581 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002582
Radek Krejcia9544502015-08-14 08:24:29 +02002583 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2584
Michal Vasko3a0043f2015-08-12 12:11:30 +02002585 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002586 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002587 goto error;
2588 }
2589
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 /* process choice's specific children */
2591 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002592 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2593 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002594 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002595 continue;
2596 }
2597
Michal Vasko29fc0182015-08-24 15:02:39 +02002598 if (!strcmp(sub->name, "container") ||
2599 !strcmp(sub->name, "leaf-list") ||
2600 !strcmp(sub->name, "leaf") ||
2601 !strcmp(sub->name, "list") ||
2602 !strcmp(sub->name, "uses") ||
2603 !strcmp(sub->name, "choice") ||
2604 !strcmp(sub->name, "anyxml")) {
2605
Michal Vaskof3930de2015-10-22 12:03:59 +02002606 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002607 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002608 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002609 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002610 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002611 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002612 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002613 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002614 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002615 goto error;
2616 }
2617
Radek Krejci1d82ef62015-08-07 14:44:40 +02002618 cs->when = read_yin_when(module, sub);
2619 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002620 goto error;
2621 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002622
Michal Vasko345da0a2015-12-02 10:35:55 +01002623 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002624 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002625 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002626 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002629
Radek Krejci3cf9e222015-06-18 11:37:50 +02002630 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002631 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002632 if (!cs->features) {
2633 LOGMEM;
2634 goto error;
2635 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002636 }
Radek Krejci73adb602015-07-02 18:07:40 +02002637 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002638 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002639 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002640 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002641 goto error;
2642 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 }
Radek Krejcib388c152015-06-04 17:03:03 +02002644
Michal Vasko29fc0182015-08-24 15:02:39 +02002645 /* last part - process data nodes */
2646 LY_TREE_FOR_SAFE(root.child, next, sub) {
2647 if (!strcmp(sub->name, "container")) {
2648 node = read_yin_container(module, retval, sub, resolve, unres);
2649 } else if (!strcmp(sub->name, "leaf-list")) {
2650 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2651 } else if (!strcmp(sub->name, "leaf")) {
2652 node = read_yin_leaf(module, retval, sub, resolve, unres);
2653 } else if (!strcmp(sub->name, "list")) {
2654 node = read_yin_list(module, retval, sub, resolve, unres);
2655 } else if (!strcmp(sub->name, "choice")) {
2656 node = read_yin_choice(module, retval, sub, resolve, unres);
2657 } else if (!strcmp(sub->name, "uses")) {
2658 node = read_yin_uses(module, retval, sub, resolve, unres);
2659 } else if (!strcmp(sub->name, "anyxml")) {
2660 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2661 }
2662 if (!node) {
2663 goto error;
2664 }
2665
Michal Vasko345da0a2015-12-02 10:35:55 +01002666 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002667 }
2668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002670
2671error:
2672
Michal Vasko29fc0182015-08-24 15:02:39 +02002673 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002674 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002675 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002676 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002679}
2680
Michal Vasko0d343d12015-08-24 14:57:36 +02002681/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002682static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002683read_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 +02002684{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002685 struct lyxml_elem *sub, *next;
2686 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002687 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002688 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002689 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002690 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002693 if (!choice) {
2694 LOGMEM;
2695 return NULL;
2696 }
Radek Krejci76512572015-08-04 09:47:08 +02002697 choice->nodetype = LYS_CHOICE;
2698 choice->prev = (struct lys_node *)choice;
2699 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002700
Michal Vaskoe0c59842015-09-24 13:52:20 +02002701 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2702 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002703 goto error;
2704 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002705
Radek Krejcia9544502015-08-14 08:24:29 +02002706 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2707
Michal Vasko3a0043f2015-08-12 12:11:30 +02002708 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002709 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002710 goto error;
2711 }
2712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 /* process choice's specific children */
2714 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002715 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2716 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002717 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002718 continue;
2719 }
2720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002722 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 goto error;
2724 }
2725 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002726 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 goto error;
2728 }
2729 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002730 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 goto error;
2732 }
2733 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002734 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 goto error;
2736 }
2737 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002738 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 goto error;
2740 }
2741 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002742 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 goto error;
2744 }
2745 } else if (!strcmp(sub->name, "default")) {
2746 if (dflt_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002747 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 goto error;
2749 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002750 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002751 } else if (!strcmp(sub->name, "mandatory")) {
2752 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002753 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002754 goto error;
2755 }
2756 /* just checking the flags in leaf is not sufficient, we would allow
2757 * multiple mandatory statements with the "false" value
2758 */
2759 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 GETVAL(value, sub, "value");
2762 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002763 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002764 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002765 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002766 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002767 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002768 goto error;
2769 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002770 } else if (!strcmp(sub->name, "when")) {
2771 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002772 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002773 goto error;
2774 }
2775
2776 choice->when = read_yin_when(module, sub);
2777 if (!choice->when) {
2778 goto error;
2779 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002780 } else if (!strcmp(sub->name, "if-feature")) {
2781 c_ftrs++;
2782
Michal Vasko345da0a2015-12-02 10:35:55 +01002783 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002784 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002786 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002789
Radek Krejci1d82ef62015-08-07 14:44:40 +02002790 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002791 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002793
Radek Krejci3cf9e222015-06-18 11:37:50 +02002794 if (c_ftrs) {
2795 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002796 if (!choice->features) {
2797 LOGMEM;
2798 goto error;
2799 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002800 }
2801
Radek Krejci73adb602015-07-02 18:07:40 +02002802 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002803 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002804 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002805 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002806 goto error;
2807 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002808 }
2809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002810 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002811 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002812 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2813 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 goto error;
2815 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002817 /* link default with the case */
2818 if (dflt_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002819 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002820 goto error;
2821 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002822 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002824 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002825
2826error:
2827
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002828 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002831}
2832
Michal Vasko0d343d12015-08-24 14:57:36 +02002833/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002834static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002835read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002836 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002837{
Radek Krejci76512572015-08-04 09:47:08 +02002838 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002839 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 struct lyxml_elem *sub, *next;
2841 const char *value;
2842 int r;
2843 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002844 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002846 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002847 if (!anyxml) {
2848 LOGMEM;
2849 return NULL;
2850 }
Radek Krejci76512572015-08-04 09:47:08 +02002851 anyxml->nodetype = LYS_ANYXML;
2852 anyxml->prev = (struct lys_node *)anyxml;
2853 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002854
Michal Vaskoe0c59842015-09-24 13:52:20 +02002855 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2856 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 goto error;
2858 }
Radek Krejci863c2852015-06-03 15:47:11 +02002859
Radek Krejcia9544502015-08-14 08:24:29 +02002860 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002861
Radek Krejcic4283442016-04-22 09:19:27 +02002862 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002863 goto error;
2864 }
2865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002867 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2868 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002869 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002870 continue;
2871 }
2872
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002873 if (!strcmp(sub->name, "mandatory")) {
2874 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002875 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002876 goto error;
2877 }
2878 /* just checking the flags in leaf is not sufficient, we would allow
2879 * multiple mandatory statements with the "false" value
2880 */
2881 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 GETVAL(value, sub, "value");
2884 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002885 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002886 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002887 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002888 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002889 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 goto error;
2891 }
2892 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002893 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002894 } else if (!strcmp(sub->name, "when")) {
2895 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002896 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002897 goto error;
2898 }
2899
2900 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002901 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002902 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002903 goto error;
2904 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002905 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 } else if (!strcmp(sub->name, "must")) {
2907 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002908 } else if (!strcmp(sub->name, "if-feature")) {
2909 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002912 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 }
2915 }
Radek Krejci863c2852015-06-03 15:47:11 +02002916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 /* middle part - process nodes with cardinality of 0..n */
2918 if (c_must) {
2919 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002920 if (!anyxml->must) {
2921 LOGMEM;
2922 goto error;
2923 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002925 if (c_ftrs) {
2926 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002927 if (!anyxml->features) {
2928 LOGMEM;
2929 goto error;
2930 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002931 }
Radek Krejci863c2852015-06-03 15:47:11 +02002932
Radek Krejci73adb602015-07-02 18:07:40 +02002933 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002935 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2936 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 if (r) {
2938 goto error;
2939 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002940 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002941 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002942 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002943 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002944 goto error;
2945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 }
Radek Krejci863c2852015-06-03 15:47:11 +02002948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002949 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002950
2951error:
2952
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002953 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02002954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002956}
2957
Michal Vasko0d343d12015-08-24 14:57:36 +02002958/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002959static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002960read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002961 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002962{
Radek Krejci76512572015-08-04 09:47:08 +02002963 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002964 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002965 struct lyxml_elem *sub, *next;
2966 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01002967 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002968 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002970 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01002971 if (!leaf) {
2972 LOGMEM;
2973 return NULL;
2974 }
Radek Krejci76512572015-08-04 09:47:08 +02002975 leaf->nodetype = LYS_LEAF;
2976 leaf->prev = (struct lys_node *)leaf;
2977 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002978
Michal Vaskoe0c59842015-09-24 13:52:20 +02002979 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2980 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 goto error;
2982 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002983
Radek Krejcia9544502015-08-14 08:24:29 +02002984 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002985
Radek Krejcic4283442016-04-22 09:19:27 +02002986 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002987 goto error;
2988 }
2989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002991 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2992 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002993 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002994 continue;
2995 }
2996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01002998 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002999 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 goto error;
3001 }
Michal Vasko88c29542015-11-27 14:57:53 +01003002 /* HACK for unres */
3003 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003004 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci48464ed2016-03-17 15:44:09 +01003005 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003006 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 goto error;
3008 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003009 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 } else if (!strcmp(sub->name, "default")) {
3011 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003012 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 goto error;
3014 }
3015 GETVAL(value, sub, "value");
3016 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3017 } else if (!strcmp(sub->name, "units")) {
3018 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003019 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 goto error;
3021 }
3022 GETVAL(value, sub, "name");
3023 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3024 } else if (!strcmp(sub->name, "mandatory")) {
3025 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003026 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 goto error;
3028 }
3029 /* just checking the flags in leaf is not sufficient, we would allow
3030 * multiple mandatory statements with the "false" value
3031 */
3032 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 GETVAL(value, sub, "value");
3035 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003036 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003037 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003038 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003039 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003040 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 goto error;
3042 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003043 } else if (!strcmp(sub->name, "when")) {
3044 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003045 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003046 goto error;
3047 }
3048
3049 leaf->when = read_yin_when(module, sub);
3050 if (!leaf->when) {
3051 goto error;
3052 }
3053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003054 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003055 c_must++;
3056 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003057 } else if (!strcmp(sub->name, "if-feature")) {
3058 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003062 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003065
Michal Vasko88c29542015-11-27 14:57:53 +01003066 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003070 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003071 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 goto error;
3073 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003074 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003075 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003076 goto error;
3077 }
Radek Krejci841ec082016-04-05 13:05:17 +02003078 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003079 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003080 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003081 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003082 goto error;
3083 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 /* middle part - process nodes with cardinality of 0..n */
3087 if (c_must) {
3088 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003089 if (!leaf->must) {
3090 LOGMEM;
3091 goto error;
3092 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003094 if (c_ftrs) {
3095 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003096 if (!leaf->features) {
3097 LOGMEM;
3098 goto error;
3099 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003100 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003101
Radek Krejci73adb602015-07-02 18:07:40 +02003102 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003103 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003104 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3105 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003106 if (r) {
3107 goto error;
3108 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003109 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003110 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003111 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003112 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003113 goto error;
3114 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003119
3120error:
3121
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003122 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003125}
3126
Michal Vasko0d343d12015-08-24 14:57:36 +02003127/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003128static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003129read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003130 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003131{
Radek Krejci76512572015-08-04 09:47:08 +02003132 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003133 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003134 struct lyxml_elem *sub, *next;
3135 const char *value;
3136 char *endptr;
3137 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003138 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003139 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003143 if (!llist) {
3144 LOGMEM;
3145 return NULL;
3146 }
Radek Krejci76512572015-08-04 09:47:08 +02003147 llist->nodetype = LYS_LEAFLIST;
3148 llist->prev = (struct lys_node *)llist;
3149 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003150
Michal Vaskoe0c59842015-09-24 13:52:20 +02003151 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3152 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 goto error;
3154 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003155
Radek Krejcia9544502015-08-14 08:24:29 +02003156 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003157
Radek Krejcic4283442016-04-22 09:19:27 +02003158 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003159 goto error;
3160 }
3161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003163 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3164 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003165 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003166 continue;
3167 }
3168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003170 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003171 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 goto error;
3173 }
Michal Vasko88c29542015-11-27 14:57:53 +01003174 /* HACK for unres */
3175 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003176 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci48464ed2016-03-17 15:44:09 +01003177 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003178 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 goto error;
3180 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003181 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 } else if (!strcmp(sub->name, "units")) {
3183 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003184 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 goto error;
3186 }
3187 GETVAL(value, sub, "name");
3188 llist->units = lydict_insert(module->ctx, value, strlen(value));
3189 } else if (!strcmp(sub->name, "ordered-by")) {
3190 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003191 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 goto error;
3193 }
3194 /* just checking the flags in llist is not sufficient, we would
3195 * allow multiple ordered-by statements with the "system" value
3196 */
3197 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003198
Radek Krejci1574a8d2015-08-03 14:16:52 +02003199 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3201 * state data
3202 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003203 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 continue;
3205 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 GETVAL(value, sub, "value");
3208 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003209 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003211 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003213 } /* else system is the default value, so we can ignore it */
3214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 } else if (!strcmp(sub->name, "must")) {
3216 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003217 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003218 } else if (!strcmp(sub->name, "if-feature")) {
3219 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003220 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 } else if (!strcmp(sub->name, "min-elements")) {
3223 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
3227 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 GETVAL(value, sub, "value");
3230 while (isspace(value[0])) {
3231 value++;
3232 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 /* convert it to uint32_t */
3235 errno = 0;
3236 endptr = NULL;
3237 val = strtoul(value, &endptr, 10);
3238 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003239 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 goto error;
3241 }
3242 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003243 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003244 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3245 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003246 goto error;
3247 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003248 } else if (!strcmp(sub->name, "max-elements")) {
3249 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003250 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 goto error;
3252 }
3253 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 GETVAL(value, sub, "value");
3256 while (isspace(value[0])) {
3257 value++;
3258 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003259
Radek Krejci0d7b2472016-02-12 11:11:03 +01003260 if (!strcmp(value, "unbounded")) {
3261 llist->max = 0;
3262 } else {
3263 /* convert it to uint32_t */
3264 errno = 0;
3265 endptr = NULL;
3266 val = strtoul(value, &endptr, 10);
3267 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003268 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003269 goto error;
3270 }
3271 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003272 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003273 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3274 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003275 goto error;
3276 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003278 } else if (!strcmp(sub->name, "when")) {
3279 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003280 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003281 goto error;
3282 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003283
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003284 llist->when = read_yin_when(module, sub);
3285 if (!llist->when) {
3286 goto error;
3287 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003289 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003292
Michal Vasko88c29542015-11-27 14:57:53 +01003293 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003297 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003298 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 goto error;
3300 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 /* middle part - process nodes with cardinality of 0..n */
3303 if (c_must) {
3304 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003305 if (!llist->must) {
3306 LOGMEM;
3307 goto error;
3308 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003310 if (c_ftrs) {
3311 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003312 if (!llist->features) {
3313 LOGMEM;
3314 goto error;
3315 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003316 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003317
Radek Krejci73adb602015-07-02 18:07:40 +02003318 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003320 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3321 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003322 if (r) {
3323 goto error;
3324 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003325 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003326 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003327 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003328 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003329 goto error;
3330 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003335
3336error:
3337
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003338 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003341}
3342
Michal Vasko0d343d12015-08-24 14:57:36 +02003343/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003344static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003345read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3346 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003347{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003348 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003349 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003351 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003352 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003354 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 char *auxs;
3356 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 /* init */
3359 memset(&root, 0, sizeof root);
3360 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003363 if (!list) {
3364 LOGMEM;
3365 return NULL;
3366 }
Radek Krejci76512572015-08-04 09:47:08 +02003367 list->nodetype = LYS_LIST;
3368 list->prev = (struct lys_node *)list;
3369 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003370
Michal Vaskoe0c59842015-09-24 13:52:20 +02003371 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3372 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 goto error;
3374 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003375
Radek Krejcia9544502015-08-14 08:24:29 +02003376 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003378 /* process list's specific children */
3379 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003380 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3381 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003382 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003383 continue;
3384 }
3385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 /* data statements */
3387 if (!strcmp(sub->name, "container") ||
3388 !strcmp(sub->name, "leaf-list") ||
3389 !strcmp(sub->name, "leaf") ||
3390 !strcmp(sub->name, "list") ||
3391 !strcmp(sub->name, "choice") ||
3392 !strcmp(sub->name, "uses") ||
3393 !strcmp(sub->name, "grouping") ||
3394 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003395 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003396 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 /* array counters */
3399 } else if (!strcmp(sub->name, "key")) {
3400 /* check cardinality 0..1 */
3401 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003402 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 goto error;
3404 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 /* count the number of keys */
3407 GETVAL(value, sub, "value");
3408 key_str = value;
3409 while ((value = strpbrk(value, " \t\n"))) {
3410 list->keys_size++;
3411 while (isspace(*value)) {
3412 value++;
3413 }
3414 }
3415 list->keys_size++;
3416 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003417 if (!list->keys) {
3418 LOGMEM;
3419 goto error;
3420 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 } else if (!strcmp(sub->name, "unique")) {
3422 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003423 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003424 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 } else if (!strcmp(sub->name, "typedef")) {
3426 c_tpdf++;
3427 } else if (!strcmp(sub->name, "must")) {
3428 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003429 } else if (!strcmp(sub->name, "if-feature")) {
3430 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 /* optional stetments */
3433 } else if (!strcmp(sub->name, "ordered-by")) {
3434 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003435 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 goto error;
3437 }
3438 /* just checking the flags in llist is not sufficient, we would
3439 * allow multiple ordered-by statements with the "system" value
3440 */
3441 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003442
Radek Krejci1574a8d2015-08-03 14:16:52 +02003443 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3445 * state data
3446 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003447 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 continue;
3449 }
Radek Krejci345ad742015-06-03 11:04:18 +02003450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 GETVAL(value, sub, "value");
3452 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003453 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003455 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
3458 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003459 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 } else if (!strcmp(sub->name, "min-elements")) {
3461 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003462 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 goto error;
3464 }
3465 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 GETVAL(value, sub, "value");
3468 while (isspace(value[0])) {
3469 value++;
3470 }
Radek Krejci345ad742015-06-03 11:04:18 +02003471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 /* convert it to uint32_t */
3473 errno = 0;
3474 auxs = NULL;
3475 val = strtoul(value, &auxs, 10);
3476 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003477 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 goto error;
3479 }
3480 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003481 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003482 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3483 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003484 lyxml_free(module->ctx, sub);
3485 goto error;
3486 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003487 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 } else if (!strcmp(sub->name, "max-elements")) {
3489 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003490 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 goto error;
3492 }
3493 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 GETVAL(value, sub, "value");
3496 while (isspace(value[0])) {
3497 value++;
3498 }
Radek Krejci345ad742015-06-03 11:04:18 +02003499
Radek Krejci0d7b2472016-02-12 11:11:03 +01003500 if (!strcmp(value, "unbounded")) {
3501 list->max = 0;;
3502 } else {
3503 /* convert it to uint32_t */
3504 errno = 0;
3505 auxs = NULL;
3506 val = strtoul(value, &auxs, 10);
3507 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003508 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003509 goto error;
3510 }
3511 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003512 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003513 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3514 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003515 goto error;
3516 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003518 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003519 } else if (!strcmp(sub->name, "when")) {
3520 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003521 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003522 goto error;
3523 }
3524
3525 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003526 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003527 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003528 goto error;
3529 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003530 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003531 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003532 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003533 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 }
3535 }
Radek Krejci345ad742015-06-03 11:04:18 +02003536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003538 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003539 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 goto error;
3541 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3544 if (c_tpdf) {
3545 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003546 if (!list->tpdf) {
3547 LOGMEM;
3548 goto error;
3549 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003551 if (c_must) {
3552 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003553 if (!list->must) {
3554 LOGMEM;
3555 goto error;
3556 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003557 }
3558 if (c_ftrs) {
3559 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003560 if (!list->features) {
3561 LOGMEM;
3562 goto error;
3563 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003564 }
Radek Krejci73adb602015-07-02 18:07:40 +02003565 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003567 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3568 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003569 if (r) {
3570 goto error;
3571 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003572 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003573 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003574 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003575 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003576 goto error;
3577 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003578 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003579 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3580 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003581 if (r) {
3582 goto error;
3583 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 }
3585 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003586
Radek Krejcic4283442016-04-22 09:19:27 +02003587 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003588 goto error;
3589 }
3590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003591 /* last part - process data nodes */
3592 LY_TREE_FOR_SAFE(root.child, next, sub) {
3593 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003594 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003596 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003598 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003600 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003602 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003604 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003606 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003608 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003609 } else {
3610 LOGINT;
3611 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003613 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 goto error;
3615 }
Radek Krejci73adb602015-07-02 18:07:40 +02003616
Michal Vasko345da0a2015-12-02 10:35:55 +01003617 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003619
Radek Krejci461efb92016-02-12 15:52:18 +01003620 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003621 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003622 goto error;
3623 }
3624 } /* 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 +02003625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 /* process unique statements */
3627 if (c_uniq) {
3628 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003629 if (!list->unique) {
3630 LOGMEM;
3631 goto error;
3632 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003633
Radek Krejci461efb92016-02-12 15:52:18 +01003634 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3635 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3636 list->unique_size++;
3637 if (r) {
3638 goto error;
3639 }
3640
3641 lyxml_free(module->ctx, sub);
3642 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003644
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003645 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003646
3647error:
3648
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003649 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003651 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 }
3653 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003654 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003658}
3659
Michal Vasko0d343d12015-08-24 14:57:36 +02003660/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003661static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003662read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3663 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003664{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003666 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003667 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003668 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 const char *value;
3670 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003671 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003673 /* init */
3674 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003676 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003677 if (!cont) {
3678 LOGMEM;
3679 return NULL;
3680 }
Radek Krejci76512572015-08-04 09:47:08 +02003681 cont->nodetype = LYS_CONTAINER;
3682 cont->prev = (struct lys_node *)cont;
3683 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003684
Michal Vaskoe0c59842015-09-24 13:52:20 +02003685 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3686 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 goto error;
3688 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003689
Radek Krejcia9544502015-08-14 08:24:29 +02003690 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003692 /* process container's specific children */
3693 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003694 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003695 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003696 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003697 continue;
3698 }
3699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 if (!strcmp(sub->name, "presence")) {
3701 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003702 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 goto error;
3704 }
3705 GETVAL(value, sub, "value");
3706 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003707
Michal Vasko345da0a2015-12-02 10:35:55 +01003708 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003709 } else if (!strcmp(sub->name, "when")) {
3710 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003711 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003712 goto error;
3713 }
3714
3715 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003716 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003717 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003718 goto error;
3719 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003720 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 /* data statements */
3723 } else if (!strcmp(sub->name, "container") ||
3724 !strcmp(sub->name, "leaf-list") ||
3725 !strcmp(sub->name, "leaf") ||
3726 !strcmp(sub->name, "list") ||
3727 !strcmp(sub->name, "choice") ||
3728 !strcmp(sub->name, "uses") ||
3729 !strcmp(sub->name, "grouping") ||
3730 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003731 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003732 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 /* array counters */
3735 } else if (!strcmp(sub->name, "typedef")) {
3736 c_tpdf++;
3737 } else if (!strcmp(sub->name, "must")) {
3738 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003739 } else if (!strcmp(sub->name, "if-feature")) {
3740 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003741 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003742 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 }
3745 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003747 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3748 if (c_tpdf) {
3749 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003750 if (!cont->tpdf) {
3751 LOGMEM;
3752 goto error;
3753 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 }
3755 if (c_must) {
3756 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003757 if (!cont->must) {
3758 LOGMEM;
3759 goto error;
3760 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003762 if (c_ftrs) {
3763 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003764 if (!cont->features) {
3765 LOGMEM;
3766 goto error;
3767 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003768 }
Radek Krejci800af702015-06-02 13:46:01 +02003769
Radek Krejci73adb602015-07-02 18:07:40 +02003770 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003772 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3773 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 if (r) {
3775 goto error;
3776 }
3777 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003778 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3779 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 if (r) {
3781 goto error;
3782 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003783 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003784 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003785 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003786 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003787 goto error;
3788 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003791
Radek Krejcic4283442016-04-22 09:19:27 +02003792 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003793 goto error;
3794 }
3795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003796 /* last part - process data nodes */
3797 LY_TREE_FOR_SAFE(root.child, next, sub) {
3798 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003799 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003801 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003803 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003805 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003806 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003807 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003809 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003811 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003813 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003815 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 goto error;
3817 }
Radek Krejci73adb602015-07-02 18:07:40 +02003818
Michal Vasko345da0a2015-12-02 10:35:55 +01003819 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003823
3824error:
3825
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003826 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003828 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003832}
3833
Michal Vasko0d343d12015-08-24 14:57:36 +02003834/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003835static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003837 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003838{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003841 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003842 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 int r;
3844 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 /* init */
3847 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003850 if (!grp) {
3851 LOGMEM;
3852 return NULL;
3853 }
Radek Krejci76512572015-08-04 09:47:08 +02003854 grp->nodetype = LYS_GROUPING;
3855 grp->prev = (struct lys_node *)grp;
3856 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003857
Michal Vasko71e1aa82015-08-12 12:17:51 +02003858 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 goto error;
3860 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003861
Radek Krejcia9544502015-08-14 08:24:29 +02003862 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3863
Radek Krejci1d82ef62015-08-07 14:44:40 +02003864 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003865 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3866 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003867 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003868 continue;
3869 }
3870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 /* data statements */
3872 if (!strcmp(sub->name, "container") ||
3873 !strcmp(sub->name, "leaf-list") ||
3874 !strcmp(sub->name, "leaf") ||
3875 !strcmp(sub->name, "list") ||
3876 !strcmp(sub->name, "choice") ||
3877 !strcmp(sub->name, "uses") ||
3878 !strcmp(sub->name, "grouping") ||
3879 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003880 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003881 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003883 /* array counters */
3884 } else if (!strcmp(sub->name, "typedef")) {
3885 c_tpdf++;
3886 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003887 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 goto error;
3889 }
3890 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3893 if (c_tpdf) {
3894 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003895 if (!grp->tpdf) {
3896 LOGMEM;
3897 goto error;
3898 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003900 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003901 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3902 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003903 if (r) {
3904 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003906 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003907
Radek Krejcic4283442016-04-22 09:19:27 +02003908 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003909 goto error;
3910 }
3911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 /* last part - process data nodes */
3913 LY_TREE_FOR_SAFE(root.child, next, sub) {
3914 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003915 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003916 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003917 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003919 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003920 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003921 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003923 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003925 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003927 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003929 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003931 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 goto error;
3933 }
Radek Krejci73adb602015-07-02 18:07:40 +02003934
Michal Vasko345da0a2015-12-02 10:35:55 +01003935 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003939
3940error:
3941
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003942 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003944 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003948}
3949
Michal Vasko0d343d12015-08-24 14:57:36 +02003950/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003951static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003952read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3953 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003954{
Radek Krejcie0674f82015-06-15 13:58:51 +02003955 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003957 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003958 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003959 int r;
3960 int c_tpdf = 0;
3961
Radek Krejcie0674f82015-06-15 13:58:51 +02003962 /* init */
3963 memset(&root, 0, sizeof root);
3964
Michal Vasko38d01f72015-06-15 09:41:06 +02003965 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01003966 if (!inout) {
3967 LOGMEM;
3968 return NULL;
3969 }
Radek Krejci6acc8012015-08-13 09:07:04 +02003970 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003971
3972 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003973 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02003974 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02003975 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003976 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02003977 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02003978 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003979 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003980 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003981 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003982 }
3983
Radek Krejci76512572015-08-04 09:47:08 +02003984 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003985
Radek Krejci6a113852015-07-03 16:04:20 +02003986 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003987 goto error;
3988 }
3989
Radek Krejcia9544502015-08-14 08:24:29 +02003990 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3991
Michal Vasko38d01f72015-06-15 09:41:06 +02003992 /* data statements */
3993 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003994 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3995 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003996 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003997 continue;
3998 }
3999
Michal Vasko38d01f72015-06-15 09:41:06 +02004000 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 !strcmp(sub->name, "leaf-list") ||
4002 !strcmp(sub->name, "leaf") ||
4003 !strcmp(sub->name, "list") ||
4004 !strcmp(sub->name, "choice") ||
4005 !strcmp(sub->name, "uses") ||
4006 !strcmp(sub->name, "grouping") ||
4007 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004008 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004009 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004011 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004012 } else if (!strcmp(sub->name, "typedef")) {
4013 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004014
Michal Vasko38d01f72015-06-15 09:41:06 +02004015 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004016 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004017 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004018 }
4019 }
4020
4021 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4022 if (c_tpdf) {
4023 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004024 if (!inout->tpdf) {
4025 LOGMEM;
4026 goto error;
4027 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004028 }
4029
Radek Krejci73adb602015-07-02 18:07:40 +02004030 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004031 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4032 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004033 if (r) {
4034 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004035 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004036 }
4037
Radek Krejcic4283442016-04-22 09:19:27 +02004038 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004039 goto error;
4040 }
4041
Michal Vasko38d01f72015-06-15 09:41:06 +02004042 /* last part - process data nodes */
4043 LY_TREE_FOR_SAFE(root.child, next, sub) {
4044 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004045 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004046 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004047 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004048 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004049 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004050 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004051 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004052 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004053 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004054 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004055 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004056 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004057 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004058 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004059 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004060 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004061 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004062 goto error;
4063 }
Radek Krejci73adb602015-07-02 18:07:40 +02004064
Michal Vasko345da0a2015-12-02 10:35:55 +01004065 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004066 }
4067
Michal Vasko38d01f72015-06-15 09:41:06 +02004068 return retval;
4069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004070error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004071
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004072 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004073 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004074 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004075 }
4076
4077 return NULL;
4078}
4079
Michal Vasko0d343d12015-08-24 14:57:36 +02004080/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004081static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004082read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4083 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004084{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004085 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004086 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004087 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004088 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004089 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004090 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004091
Michal Vaskoc6551b32015-06-16 10:51:43 +02004092 memset(&root, 0, sizeof root);
4093
Michal Vasko0ea41032015-06-16 08:53:55 +02004094 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004095 if (!notif) {
4096 LOGMEM;
4097 return NULL;
4098 }
Radek Krejci76512572015-08-04 09:47:08 +02004099 notif->nodetype = LYS_NOTIF;
4100 notif->prev = (struct lys_node *)notif;
4101 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004102
Radek Krejci6a113852015-07-03 16:04:20 +02004103 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004104 goto error;
4105 }
4106
Radek Krejcia9544502015-08-14 08:24:29 +02004107 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4108
Michal Vasko0ea41032015-06-16 08:53:55 +02004109 /* process rpc's specific children */
4110 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004111 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4112 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004113 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004114 continue;
4115 }
4116
Michal Vasko0ea41032015-06-16 08:53:55 +02004117 /* data statements */
4118 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004119 !strcmp(sub->name, "leaf-list") ||
4120 !strcmp(sub->name, "leaf") ||
4121 !strcmp(sub->name, "list") ||
4122 !strcmp(sub->name, "choice") ||
4123 !strcmp(sub->name, "uses") ||
4124 !strcmp(sub->name, "grouping") ||
4125 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004126 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004127 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004129 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004130 } else if (!strcmp(sub->name, "typedef")) {
4131 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004132 } else if (!strcmp(sub->name, "if-feature")) {
4133 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004134 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004135 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004136 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004137 }
4138 }
4139
4140 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4141 if (c_tpdf) {
4142 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004143 if (!notif->tpdf) {
4144 LOGMEM;
4145 goto error;
4146 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004147 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004148 if (c_ftrs) {
4149 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004150 if (!notif->features) {
4151 LOGMEM;
4152 goto error;
4153 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004154 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004155
Radek Krejci73adb602015-07-02 18:07:40 +02004156 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004157 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004158 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4159 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004160 if (r) {
4161 goto error;
4162 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004163 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004164 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004165 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004166 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004167 goto error;
4168 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004169 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004170 }
4171
Radek Krejcic4283442016-04-22 09:19:27 +02004172 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004173 goto error;
4174 }
4175
Michal Vasko0ea41032015-06-16 08:53:55 +02004176 /* last part - process data nodes */
4177 LY_TREE_FOR_SAFE(root.child, next, sub) {
4178 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004179 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004180 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004181 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004182 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004183 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004184 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004185 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004186 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004187 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004188 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004189 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004190 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004191 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004192 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004193 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004194 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004195 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004196 goto error;
4197 }
Radek Krejci73adb602015-07-02 18:07:40 +02004198
Michal Vasko345da0a2015-12-02 10:35:55 +01004199 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004200 }
4201
Michal Vasko0ea41032015-06-16 08:53:55 +02004202 return retval;
4203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004204error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004205
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004206 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004207 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004208 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004209 }
4210
4211 return NULL;
4212}
4213
Michal Vasko0d343d12015-08-24 14:57:36 +02004214/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004215static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004216read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4217 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004218{
Radek Krejcie0674f82015-06-15 13:58:51 +02004219 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004220 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004221 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004222 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004223 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004224 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004225
Radek Krejcie0674f82015-06-15 13:58:51 +02004226 /* init */
4227 memset(&root, 0, sizeof root);
4228
Michal Vasko38d01f72015-06-15 09:41:06 +02004229 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004230 if (!rpc) {
4231 LOGMEM;
4232 return NULL;
4233 }
Radek Krejci76512572015-08-04 09:47:08 +02004234 rpc->nodetype = LYS_RPC;
4235 rpc->prev = (struct lys_node *)rpc;
4236 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004237
Radek Krejci6a113852015-07-03 16:04:20 +02004238 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004239 goto error;
4240 }
4241
Radek Krejcia9544502015-08-14 08:24:29 +02004242 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4243
Michal Vasko38d01f72015-06-15 09:41:06 +02004244 /* process rpc's specific children */
4245 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004246 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4247 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004248 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004249 continue;
4250 }
4251
Michal Vasko38d01f72015-06-15 09:41:06 +02004252 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004253 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004254 && (rpc->child->nodetype == LYS_INPUT
4255 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004256 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004257 goto error;
4258 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004259 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004260 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004261 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004262 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004263 && (rpc->child->nodetype == LYS_INPUT
4264 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004265 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004266 goto error;
4267 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004268 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004269 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004272 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004273 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004274 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004277 } else if (!strcmp(sub->name, "typedef")) {
4278 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004279 } else if (!strcmp(sub->name, "if-feature")) {
4280 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004281 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004282 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004283 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004284 }
4285 }
4286
4287 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4288 if (c_tpdf) {
4289 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004290 if (!rpc->tpdf) {
4291 LOGMEM;
4292 goto error;
4293 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004294 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004295 if (c_ftrs) {
4296 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004297 if (!rpc->features) {
4298 LOGMEM;
4299 goto error;
4300 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004301 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004302
Radek Krejci73adb602015-07-02 18:07:40 +02004303 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004304 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004305 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4306 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004307 if (r) {
4308 goto error;
4309 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004310 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004311 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004312 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004313 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004314 goto error;
4315 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004316 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004317 }
4318
Radek Krejcic4283442016-04-22 09:19:27 +02004319 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004320 goto error;
4321 }
4322
Michal Vasko38d01f72015-06-15 09:41:06 +02004323 /* last part - process data nodes */
4324 LY_TREE_FOR_SAFE(root.child, next, sub) {
4325 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004326 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004327 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004328 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004329 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004330 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004331 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004332 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004333 goto error;
4334 }
Radek Krejci73adb602015-07-02 18:07:40 +02004335
Michal Vasko345da0a2015-12-02 10:35:55 +01004336 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004337 }
4338
Michal Vasko38d01f72015-06-15 09:41:06 +02004339 return retval;
4340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004342
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004343 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004344 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004345 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004346 }
4347
4348 return NULL;
4349}
4350
Michal Vasko0d343d12015-08-24 14:57:36 +02004351/* logs directly
4352 *
Radek Krejci74705112015-06-05 10:25:44 +02004353 * resolve - referenced grouping should be bounded to the namespace (resolved)
4354 * only when uses does not appear in grouping. In a case of grouping's uses,
4355 * we just get information but we do not apply augment or refine to it.
4356 */
Radek Krejci76512572015-08-04 09:47:08 +02004357static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004358read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004359 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004360{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004361 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004362 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004363 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004365 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004368 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004369 if (!uses) {
4370 LOGMEM;
4371 return NULL;
4372 }
Radek Krejci76512572015-08-04 09:47:08 +02004373 uses->nodetype = LYS_USES;
4374 uses->prev = (struct lys_node *)uses;
4375 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004376
Radek Krejcia9544502015-08-14 08:24:29 +02004377 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004379
Michal Vaskoe0c59842015-09-24 13:52:20 +02004380 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4381 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 goto error;
4383 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004384
Radek Krejcia9544502015-08-14 08:24:29 +02004385 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004387 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004388 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004389 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4390 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004391 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004392 continue;
4393 }
4394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 if (!strcmp(sub->name, "refine")) {
4396 c_ref++;
4397 } else if (!strcmp(sub->name, "augment")) {
4398 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004399 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004400 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004401 } else if (!strcmp(sub->name, "when")) {
4402 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004403 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004404 goto error;
4405 }
4406
4407 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004408 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004409 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004410 goto error;
4411 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004412 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004414 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 }
4417 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 /* process properties with cardinality 0..n */
4420 if (c_ref) {
4421 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004422 if (!uses->refine) {
4423 LOGMEM;
4424 goto error;
4425 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 }
4427 if (c_aug) {
4428 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004429 if (!uses->augment) {
4430 LOGMEM;
4431 goto error;
4432 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004434 if (c_ftrs) {
4435 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004436 if (!uses->features) {
4437 LOGMEM;
4438 goto error;
4439 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004440 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004441
Radek Krejcic4283442016-04-22 09:19:27 +02004442 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004443 goto error;
4444 }
4445
Radek Krejcia9544502015-08-14 08:24:29 +02004446 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004448 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4449 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004450 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004451 goto error;
4452 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004453 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004454 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4455 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004456 if (r) {
4457 goto error;
4458 }
4459 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004460 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004461 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004462 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004463 goto error;
4464 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 }
4466 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004467
Radek Krejci48464ed2016-03-17 15:44:09 +01004468 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004469 goto error;
4470 }
Radek Krejci74705112015-06-05 10:25:44 +02004471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004472 if (resolve) {
4473 /* inherit config flag */
4474 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004475 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 } else {
4477 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004478 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 }
4480 }
Radek Krejcib388c152015-06-04 17:03:03 +02004481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004482 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004483
4484error:
4485
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004486 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004489}
4490
Michal Vasko0d343d12015-08-24 14:57:36 +02004491/* logs directly
4492 *
4493 * common code for yin_read_module() and yin_read_submodule()
4494 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495static int
Radek Krejcic071c542016-01-27 14:57:51 +01004496read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4497 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004498{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004500 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004501 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004502 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004503 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004505 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01004506 int inc_size_aux = 0;
4507 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004508 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004509 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 +02004510
Radek Krejcic071c542016-01-27 14:57:51 +01004511 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004512 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 /* init */
4515 memset(&root, 0, sizeof root);
4516 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004517 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 /*
4520 * in the first run, we process elements with cardinality of 1 or 0..1 and
4521 * count elements with cardinality 0..n. Data elements (choices, containers,
4522 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4523 * need have all top-level and groupings already prepared at that time. In
4524 * the middle loop, we process other elements with carinality of 0..n since
4525 * we need to allocate arrays to store them.
4526 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004527 LY_TREE_FOR_SAFE(yin->child, next, child) {
4528 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004529 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004530 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 continue;
4532 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004533
Radek Krejcic071c542016-01-27 14:57:51 +01004534 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004536 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 goto error;
4538 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004539 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004541 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004542 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004544 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004545 goto error;
4546 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004547 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004548 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 goto error;
4550 }
4551 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004552 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004553 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4554 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004555 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 goto error;
4557 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004558 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004559 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004560 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 goto error;
4562 }
Radek Krejcif3886932015-06-04 17:36:06 +02004563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004565 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004566 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004568 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004569 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004571 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004572 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 goto error;
4574 }
4575 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004576 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 /* check here differs from a generic prefix check, since this prefix
4578 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004579 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004580 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 goto error;
4582 }
Radek Krejcic071c542016-01-27 14:57:51 +01004583 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004586 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004587
4588 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004589 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004591 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004593 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004595 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004597 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004599 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004600 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004601 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004602 lyxml_unlink_elem(ctx, child, 2);
4603 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004604
Radek Krejci1d82ef62015-08-07 14:44:40 +02004605 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004606 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004608 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004611 } else if (!strcmp(child->name, "container") ||
4612 !strcmp(child->name, "leaf-list") ||
4613 !strcmp(child->name, "leaf") ||
4614 !strcmp(child->name, "list") ||
4615 !strcmp(child->name, "choice") ||
4616 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004617 !strcmp(child->name, "anyxml") ||
4618 !strcmp(child->name, "rpc") ||
4619 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004620 lyxml_unlink_elem(ctx, child, 2);
4621 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004622
Radek Krejci1d82ef62015-08-07 14:44:40 +02004623 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004625 lyxml_unlink_elem(ctx, child, 2);
4626 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004630 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004631 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 goto error;
4633 }
Radek Krejcic071c542016-01-27 14:57:51 +01004634 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004635 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004636 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004637 goto error;
4638 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004640 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004641 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 goto error;
4643 }
Radek Krejcic071c542016-01-27 14:57:51 +01004644 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004645 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004646 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 goto error;
4648 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004649 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004650 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004651 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 goto error;
4653 }
Radek Krejcic071c542016-01-27 14:57:51 +01004654 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004655 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004656 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 goto error;
4658 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004659 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004660 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004661 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 goto error;
4663 }
Radek Krejcic071c542016-01-27 14:57:51 +01004664 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004665 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004666 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 goto error;
4668 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004669 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004670 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004671 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004672 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 goto error;
4674 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004675 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 if (strcmp(value, "1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004677 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 goto error;
4679 }
Radek Krejcic071c542016-01-27 14:57:51 +01004680 version_flag = 1;
4681 if (!submodule) {
4682 module->version = 1;
4683 } /* 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 +01004684 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004685
Radek Krejci1d82ef62015-08-07 14:44:40 +02004686 } else if (!strcmp(child->name, "extension")) {
4687 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004688
Radek Krejci3d468122015-10-02 13:36:12 +02004689 /* we have the following supported (hardcoded) extensions: */
4690 /* ietf-netconf's get-filter-element-attributes */
4691 if (!strcmp(module->ns, LY_NSNC) &&
4692 !strcmp(value, "get-filter-element-attributes")) {
4693 LOGDBG("NETCONF filter extension found");
4694 /* NACM's default-deny-write and default-deny-all */
4695 } else if (!strcmp(module->ns, LY_NSNACM) &&
4696 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4697 LOGDBG("NACM extension found");
4698 /* other extensions are not supported, so inform about such an extension */
4699 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004700 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004701 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004702 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004703 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004705 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004706 }
4707 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004708
Radek Krejcic071c542016-01-27 14:57:51 +01004709 /* check for mandatory statements */
4710 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004711 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004712 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004713 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004715 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 goto error;
4717 }
4718 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004719 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004720 goto error;
4721 }
4722 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 /* allocate arrays for elements with cardinality of 0..n */
4725 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004726 trg->imp = calloc(c_imp, sizeof *trg->imp);
4727 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004728 LOGMEM;
4729 goto error;
4730 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 }
4732 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004733 trg->rev = calloc(c_rev, sizeof *trg->rev);
4734 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004735 LOGMEM;
4736 goto error;
4737 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 }
4739 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004740 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4741 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004742 LOGMEM;
4743 goto error;
4744 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 }
4746 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004747 trg->ident = calloc(c_ident, sizeof *trg->ident);
4748 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004749 LOGMEM;
4750 goto error;
4751 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 }
4753 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004754 trg->inc = calloc(c_inc, sizeof *trg->inc);
4755 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004756 LOGMEM;
4757 goto error;
4758 }
Radek Krejcic071c542016-01-27 14:57:51 +01004759 trg->inc_size = c_inc;
4760 /* trg->inc_size can be updated by the included submodules,
4761 * so we will use inc_size_aux here, trg->inc_size stores the
4762 * target size of the array
4763 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004765 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004766 trg->augment = calloc(c_aug, sizeof *trg->augment);
4767 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004768 LOGMEM;
4769 goto error;
4770 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004771 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004772 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004773 trg->features = calloc(c_ftrs, sizeof *trg->features);
4774 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004775 LOGMEM;
4776 goto error;
4777 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004778 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004779 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004780 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4781 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004782 LOGMEM;
4783 goto error;
4784 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004785 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004786
Michal Vasko2f7925f2015-10-21 15:06:56 +02004787 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4788 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004789 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004790 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4791 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004792 if (r) {
4793 goto error;
4794 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004796 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004797 for (i = 0; i < trg->imp_size - 1; i++) {
4798 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004799 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->imp[i].module->name, "import");
4800 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 goto error;
4802 }
4803 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004804
Radek Krejci1d82ef62015-08-07 14:44:40 +02004805 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004806 memset(&inc, 0, sizeof inc);
4807 /* 1) pass module, not trg, since we want to pass the main module
4808 * 2) we cannot pass directly the structure in the array since
4809 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004810 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004811 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4812 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 if (r) {
4814 goto error;
4815 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004818 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004819 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 +01004820 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
4821 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01004822 trg->inc[inc_size_aux - 1].submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004823 goto error;
4824 }
4825 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004826
Radek Krejci1d82ef62015-08-07 14:44:40 +02004827 } else if (!strcmp(child->name, "revision")) {
4828 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004829 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 goto error;
4831 }
Radek Krejcic071c542016-01-27 14:57:51 +01004832 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004834 for (i = 0; i < trg->rev_size; i++) {
4835 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004836 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4837 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 }
4839 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004840
Radek Krejci1d82ef62015-08-07 14:44:40 +02004841 LY_TREE_FOR(child->child, child2) {
4842 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004843 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004844 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 goto error;
4846 }
Radek Krejcic071c542016-01-27 14:57:51 +01004847 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4848 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 goto error;
4850 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004851 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004852 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004853 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 goto error;
4855 }
Radek Krejcic071c542016-01-27 14:57:51 +01004856 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4857 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004858 goto error;
4859 }
4860 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004861 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004862 goto error;
4863 }
4864 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004867 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004869 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004870 if (!value) {
4871 LOGMEM;
4872 goto error;
4873 }
Radek Krejcic071c542016-01-27 14:57:51 +01004874 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4875 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004877
Radek Krejci749190d2016-02-18 16:26:25 +01004878 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004879 value = trg->rev[0].dsc;
4880 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4881 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004883
Radek Krejci749190d2016-02-18 16:26:25 +01004884 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004885 value = trg->rev[0].ref;
4886 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4887 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 }
4889 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004890
Radek Krejcic071c542016-01-27 14:57:51 +01004891 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004892
Radek Krejci1d82ef62015-08-07 14:44:40 +02004893 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004894 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4895 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 if (r) {
4897 goto error;
4898 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004899
Radek Krejci1d82ef62015-08-07 14:44:40 +02004900 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004901 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4902 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 if (r) {
4904 goto error;
4905 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004906
Radek Krejci1d82ef62015-08-07 14:44:40 +02004907 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004908 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4909 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004910 if (r) {
4911 goto error;
4912 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004913
Radek Krejci1d82ef62015-08-07 14:44:40 +02004914 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004915 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4916 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004917 if (r) {
4918 goto error;
4919 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004920 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4921 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004923 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004925
Pavol Vicane994fda2016-03-22 10:47:58 +01004926 if (submodule && lyp_propagate_submodule(module, submodule)) {
Pavol Vicanaa1eba92016-03-09 12:27:11 +01004927 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004928 }
4929
Radek Krejcif5be10f2015-06-16 13:29:36 +02004930 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004931 * refer to them. Submodule's data nodes are stored in the
4932 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004934 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004935 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004936 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 goto error;
4938 }
Radek Krejci74705112015-06-05 10:25:44 +02004939
Michal Vasko345da0a2015-12-02 10:35:55 +01004940 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004941 }
Radek Krejci74705112015-06-05 10:25:44 +02004942
Radek Krejcif5be10f2015-06-16 13:29:36 +02004943 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004944 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004945
Radek Krejci1d82ef62015-08-07 14:44:40 +02004946 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004947 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004948 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004949 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004950 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004951 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004952 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004953 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004954 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004955 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004956 } else if (!strcmp(child->name, "uses")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004957 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004958 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004959 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004960 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004961 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004962 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004963 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004965 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 goto error;
4967 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004968
Michal Vasko345da0a2015-12-02 10:35:55 +01004969 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004970 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004971
Michal Vasko2f7925f2015-10-21 15:06:56 +02004972 /* ... and finally augments (last, so we can augment our data, for instance) */
4973 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004974 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
4975 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004976
Michal Vasko2f7925f2015-10-21 15:06:56 +02004977 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004978 goto error;
4979 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004980 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004981 }
4982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004984
4985error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 /* cleanup */
4987 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004988 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004989 }
4990 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004991 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004993 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004994 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004995 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004998}
4999
Michal Vasko0d343d12015-08-24 14:57:36 +02005000/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005001struct lys_submodule *
5002yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005003{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005005 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005007
Michal Vasko5a721fd2016-02-16 12:16:48 +01005008 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005009
Radek Krejci722b0072016-02-01 17:09:45 +01005010 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005011 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005012 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005015 /* check root element */
5016 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005017 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 goto error;
5019 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005022 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 goto error;
5024 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005025
Michal Vasko5a721fd2016-02-16 12:16:48 +01005026 submodule = calloc(1, sizeof *submodule);
5027 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 LOGMEM;
5029 goto error;
5030 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005031
Michal Vasko5a721fd2016-02-16 12:16:48 +01005032 submodule->ctx = module->ctx;
5033 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5034 submodule->type = 1;
5035 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005036
Michal Vasko5a721fd2016-02-16 12:16:48 +01005037 LOGVRB("Reading submodule \"%s\".", submodule->name);
5038 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 goto error;
5040 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005042 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005043 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005044
Michal Vasko5a721fd2016-02-16 12:16:48 +01005045 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005046 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005047
5048error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005050 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005051 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005052
Michal Vasko5a721fd2016-02-16 12:16:48 +01005053 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005054 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005055 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005056 }
5057
Michal Vasko5a721fd2016-02-16 12:16:48 +01005058 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005059
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005060 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5061 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005062 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005063 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005064}
5065
Michal Vasko0d343d12015-08-24 14:57:36 +02005066/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005067struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005068yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005069{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005070 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005071 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005072 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005073 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005074 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005075
Radek Krejcic071c542016-01-27 14:57:51 +01005076 unres = calloc(1, sizeof *unres);
5077 if (!unres) {
5078 LOGMEM;
5079 return NULL;
5080 }
5081
Radek Krejci722b0072016-02-01 17:09:45 +01005082 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005083 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005084 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005087 /* check root element */
5088 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005089 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
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 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005094 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005095 goto error;
5096 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005098 module = calloc(1, sizeof *module);
5099 if (!module) {
5100 LOGMEM;
5101 goto error;
5102 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005104 module->ctx = ctx;
5105 module->name = lydict_insert(ctx, value, strlen(value));
5106 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005107 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005108
Michal Vasko9f258e42016-02-11 11:36:27 +01005109 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005110 if (read_sub_module(module, NULL, yin, unres)) {
5111 goto error;
5112 }
5113
5114 /* resolve rest of unres items */
5115 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 goto error;
5117 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005118
Radek Krejciff4874d2016-03-07 12:30:50 +01005119 if (revision) {
5120 /* check revision of the parsed model */
5121 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005122 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5123 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005124 goto error;
5125 }
5126 }
5127
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005128 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005129 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005130 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005131
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005132 if (module->augment_size || module->deviation_size) {
Michal Vasko7da5b0b2016-05-02 16:36:59 +02005133 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
Michal Vasko26055752016-05-03 11:36:31 +02005134 if (lys_module_set_implement(module)) {
5135 goto error;
5136 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005137
Michal Vasko26055752016-05-03 11:36:31 +02005138 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5139 goto error;
5140 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005141 for (i = 0; i < module->inc_size; ++i) {
Michal Vasko26055752016-05-03 11:36:31 +02005142 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5143 goto error;
5144 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005145 }
5146 }
5147
Michal Vasko345da0a2015-12-02 10:35:55 +01005148 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005149 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005150 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005152
5153error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005154 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005155 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005156 unres_schema_free(module, &unres);
5157
5158 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005159 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005160 return NULL;
5161 }
5162
5163 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005164
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005165 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005166 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005168}