blob: 90f8bd5e10d5a12251d7b3df5397a6e9b6d27fb3 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020024#include <pcre.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025
Radek Krejci998a0b82015-08-17 13:14:36 +020026#include "libyang.h"
27#include "common.h"
28#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020029#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020030#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020032#include "resolve.h"
33#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020034#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020035
Radek Krejciadb57612016-02-16 13:34:34 +010036#define GETVAL(value, node, arg) \
37 value = lyxml_get_attr(node, arg, NULL); \
38 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010039 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010040 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010041 }
Radek Krejcice7fb782015-05-29 16:52:34 +020042
Radek Krejcic6556022016-01-27 15:16:45 +010043/* parser.c */
44int dup_prefix_check(const char *prefix, struct lys_module *module);
45
Radek Krejcib388c152015-06-04 17:03:03 +020046#define OPT_IDENT 0x01
47#define OPT_CONFIG 0x02
48#define OPT_MODULE 0x04
49#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020050#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020051static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020052
Radek Krejcib8048692015-08-05 13:36:34 +020053static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020054 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020055static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020056 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020057static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020058 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020059static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020060 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020061static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020062 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020063static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020064 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020065static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020066 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020067static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020068 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020069static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020070 int resolve, struct unres_schema *unres);
71static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020072
Michal Vasko0d343d12015-08-24 14:57:36 +020073/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020074static const char *
75read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020076{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020077 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 /* there should be <text> child */
80 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010081 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010082 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010083 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084 } else if (node->child->content) {
85 len = strlen(node->child->content);
86 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010087 } else {
88 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020090}
91
Michal Vasko0d343d12015-08-24 14:57:36 +020092/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093static int
Michal Vasko1d337e12016-02-15 12:32:04 +010094fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
95{
96 int r;
97 const char *value;
98
99 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100100 if (!(value = transform_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100101 return EXIT_FAILURE;
102 }
103
104 /* HACK - store pointer to the parent node for later status check */
105 *iffeat = (struct lys_feature *)parent;
Radek Krejci48464ed2016-03-17 15:44:09 +0100106 r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value);
Michal Vasko1d337e12016-02-15 12:32:04 +0100107 lydict_remove(parent->module->ctx, value);
108 if (!r) {
109 return EXIT_SUCCESS;
110 }
111
112error:
113 return EXIT_FAILURE;
114}
115
116/* logs directly */
117static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200118fill_yin_identity(struct lys_module *module, struct lyxml_elem *yin, struct lys_ident *ident, struct unres_schema *unres)
Radek Krejci04581c62015-05-22 21:24:00 +0200119{
Radek Krejci73adb602015-07-02 18:07:40 +0200120 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200121 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100122 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200123
Michal Vasko4cfcd252015-08-03 14:31:10 +0200124 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100125 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200126
Radek Krejci76512572015-08-04 09:47:08 +0200127 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200128 return EXIT_FAILURE;
129 }
Radek Krejci04581c62015-05-22 21:24:00 +0200130
Radek Krejci73adb602015-07-02 18:07:40 +0200131 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200132 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
133 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200134 continue;
135 }
136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200137 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100138 if (base_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100139 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200140 return EXIT_FAILURE;
141 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100142 base_flag = 1;
143
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200144 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100145 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100146 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200147 return EXIT_FAILURE;
148 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100149
Radek Krejci48464ed2016-03-17 15:44:09 +0100150 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100151 lydict_remove(module->ctx, value);
152 return EXIT_FAILURE;
153 }
154 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200155 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100156 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200157 return EXIT_FAILURE;
158 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200159 }
Radek Krejci04581c62015-05-22 21:24:00 +0200160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200161 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200162
163error:
164 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200165}
166
Michal Vasko0d343d12015-08-24 14:57:36 +0200167/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200168static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200169read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200170{
Radek Krejci73adb602015-07-02 18:07:40 +0200171 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200172 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200173
Radek Krejci73adb602015-07-02 18:07:40 +0200174 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200175 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
176 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200177 continue;
178 }
179
Radek Krejci41726f92015-06-19 13:11:05 +0200180 if (!strcmp(child->name, "description")) {
181 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100182 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200183 return EXIT_FAILURE;
184 }
185 restr->dsc = read_yin_subnode(ctx, child, "text");
186 if (!restr->dsc) {
187 return EXIT_FAILURE;
188 }
189 } else if (!strcmp(child->name, "reference")) {
190 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100191 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200192 return EXIT_FAILURE;
193 }
194 restr->ref = read_yin_subnode(ctx, child, "text");
195 if (!restr->ref) {
196 return EXIT_FAILURE;
197 }
198 } else if (!strcmp(child->name, "error-app-tag")) {
199 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200201 return EXIT_FAILURE;
202 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200203 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200204 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200205 } else if (!strcmp(child->name, "error-message")) {
206 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100207 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200208 return EXIT_FAILURE;
209 }
210 restr->emsg = read_yin_subnode(ctx, child, "value");
211 if (!restr->emsg) {
212 return EXIT_FAILURE;
213 }
214 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100215 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200216 return EXIT_FAILURE;
217 }
Radek Krejci41726f92015-06-19 13:11:05 +0200218 }
219
220 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200221
222error:
223 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200224}
225
Michal Vasko88c29542015-11-27 14:57:53 +0100226/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
227int
Radek Krejcib8048692015-08-05 13:36:34 +0200228fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Michal Vaskof02e3742015-08-05 16:27:02 +0200229 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200230{
Michal Vasko1dca6882015-10-22 14:29:42 +0200231 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200232 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200233 struct lys_restr **restr;
234 struct lys_type_bit bit;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200235 struct lys_type *type_der;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200236 pcre *precomp;
237 int i, j, rc, err_offset;
Radek Krejcidc008d72016-02-17 13:12:14 +0100238 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200239 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200240 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200241
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200242 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100243 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200244 if (!value) {
245 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200246 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200247
248 i = parse_identifier(value);
249 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100250 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100251 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200252 goto error;
253 }
254 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100255 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200256 if (value[i]) {
257 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100258 name += i;
259 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100260 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100261 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200262 goto error;
263 }
Radek Krejci225376f2016-02-16 17:36:22 +0100264 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200265 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200266
Radek Krejci225376f2016-02-16 17:36:22 +0100267 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100268 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200269 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100270 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200271 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100272
273 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200274 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200275 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejcidc008d72016-02-17 13:12:14 +0100276 ret = EXIT_FAILURE;
277 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200278 }
279 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200280
Radek Krejcicf509982015-12-15 09:22:44 +0100281 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100282 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100283 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100284 return -1;
285 }
286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200287 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200288 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200289 /* RFC 6020 9.7.4 - bit */
290
291 /* get bit specifications, at least one must be present */
292 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200293 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
294 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100295 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200296 continue;
297 }
298
Radek Krejci994b6f62015-06-18 16:47:27 +0200299 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200300 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200301 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100302 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200303 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200304 }
305 }
Radek Krejciac781922015-07-09 15:35:14 +0200306 if (!type->der->type.der && !type->info.bits.count) {
307 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100308 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200309 goto error;
310 }
Radek Krejciac781922015-07-09 15:35:14 +0200311 if (type->der->type.der && type->info.bits.count) {
312 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100313 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200314 goto error;
315 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200316
317 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100318 if (!type->info.bits.bit) {
319 LOGMEM;
320 goto error;
321 }
Radek Krejci73adb602015-07-02 18:07:40 +0200322 p = 0;
323 i = -1;
324 LY_TREE_FOR(yin->child, next) {
325 i++;
326
327 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100328 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100329 goto error;
330 }
331
Radek Krejci994b6f62015-06-18 16:47:27 +0200332 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200333 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200334 type->info.bits.count = i + 1;
335 goto error;
336 }
337
338 /* check the name uniqueness */
339 for (j = 0; j < i; j++) {
340 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100341 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200342 type->info.bits.count = i + 1;
343 goto error;
344 }
345 }
346
Radek Krejci0d70c372015-07-02 16:23:10 +0200347 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200348 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200349 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
350 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200351 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200352 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200353
Radek Krejci0d70c372015-07-02 16:23:10 +0200354 if (!strcmp(node->name, "position")) {
355 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200356 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200357
358 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200359 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100360 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200361 type->info.bits.count = i + 1;
362 goto error;
363 }
364 type->info.bits.bit[i].pos = (uint32_t)p_;
365
366 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200367 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200368 p = type->info.bits.bit[i].pos;
369 p++;
370 } else {
371 /* check that the value is unique */
372 for (j = 0; j < i; j++) {
373 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100374 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100375 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200376 type->info.bits.count = i + 1;
377 goto error;
378 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200379 }
380 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200381 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100382 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200383 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200384 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200385 }
386 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200387 /* assign value automatically */
388 if (p > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100389 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200390 type->info.bits.count = i + 1;
391 goto error;
392 }
393 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100394 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200395 p++;
396 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200397
398 /* keep them ordered by position */
399 j = i;
400 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
401 /* switch them */
402 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
403 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
404 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
405 j--;
406 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200408 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200410 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200411 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200412 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200413 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
414 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200415 continue;
416 }
417
Radek Krejcif9401c32015-06-26 16:47:36 +0200418 if (!strcmp(node->name, "range")) {
419 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100420 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200421 goto error;
422 }
423
424 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200425 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100426 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200427 goto error;
428 }
429 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100430 if (!type->info.dec64.range) {
431 LOGMEM;
432 goto error;
433 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200434 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
435
436 /* get possible substatements */
437 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
438 goto error;
439 }
440 } else if (!strcmp(node->name, "fraction-digits")) {
441 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100442 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200443 goto error;
444 }
445 GETVAL(value, node, "value");
446 v = strtol(value, NULL, 10);
447
448 /* range check */
449 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100450 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200451 goto error;
452 }
453 type->info.dec64.dig = (uint8_t)v;
454 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100455 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200456 goto error;
457 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200458 }
459
460 /* mandatory sub-statement(s) check */
461 if (!type->info.dec64.dig && !type->der->type.der) {
462 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100463 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200464 goto error;
465 }
Radek Krejci7511f402015-07-10 09:56:30 +0200466 if (type->info.dec64.dig && type->der->type.der) {
467 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100468 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200469 goto error;
470 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200471 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200473 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200474 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200475
Radek Krejci994b6f62015-06-18 16:47:27 +0200476 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200478 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
479 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100480 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200481 continue;
482 }
483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200485 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200486 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100487 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200488 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 }
490 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200491 if (!type->der->type.der && !type->info.enums.count) {
492 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100493 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494 goto error;
495 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200496 if (type->der->type.der && type->info.enums.count) {
497 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100498 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200499 goto error;
500 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200501
Radek Krejci1574a8d2015-08-03 14:16:52 +0200502 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100503 if (!type->info.enums.enm) {
504 LOGMEM;
505 goto error;
506 }
Radek Krejci73adb602015-07-02 18:07:40 +0200507 v = 0;
508 i = -1;
509 LY_TREE_FOR(yin->child, next) {
510 i++;
511
512 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100513 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100514 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
515 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100516 goto error;
517 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200518 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200519 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200520 type->info.enums.count = i + 1;
521 goto error;
522 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200524 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200525 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200526 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100527 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200528 type->info.enums.count = i + 1;
529 goto error;
530 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200532 /* check the name uniqueness */
533 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200534 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100535 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200536 type->info.enums.count = i + 1;
537 goto error;
538 }
539 }
Radek Krejci04581c62015-05-22 21:24:00 +0200540
Radek Krejci0d70c372015-07-02 16:23:10 +0200541 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200542 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200543 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
544 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200545 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200546 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547
Radek Krejci0d70c372015-07-02 16:23:10 +0200548 if (!strcmp(node->name, "value")) {
549 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200550 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200551
552 /* range check */
553 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100554 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200555 type->info.enums.count = i + 1;
556 goto error;
557 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200558 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200559
560 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200561 if (type->info.enums.enm[i].value > v) {
562 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200563 v++;
564 } else {
565 /* check that the value is unique */
566 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200567 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100568 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100569 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200570 type->info.enums.count = i + 1;
571 goto error;
572 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200573 }
574 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200575 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100576 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200577 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200579 }
580 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 /* assign value automatically */
582 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100583 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 type->info.enums.count = i + 1;
585 goto error;
586 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200587 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100588 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 v++;
590 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 }
592 break;
593
594 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200595 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200596
597 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200598 LY_TREE_FOR_SAFE(yin->child, next, node) {
599 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
600 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100601 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200602 continue;
603 }
604
Michal Vaskoe29c6622015-11-27 15:02:31 +0100605 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100606 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200607 goto error;
608 }
609 }
610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200611 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200612 if (type->der->type.der) {
613 /* this is just a derived type with no base specified/required */
614 break;
615 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100616 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200617 goto error;
618 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200619 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100620 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 goto error;
622 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200623 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100624 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100625 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100626 if (!value) {
627 goto error;
628 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100629 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100630 lydict_remove(module->ctx, value);
631
632 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200633 goto error;
634 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 break;
636
637 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200638 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200639 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200640 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
641 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200642 continue;
643 }
644
Radek Krejciaf351422015-06-19 14:49:38 +0200645 if (!strcmp(node->name, "require-instance")) {
646 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100647 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200648 goto error;
649 }
650 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200651 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200652 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200653 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200654 type->info.inst.req = -1;
655 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100656 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200657 goto error;
658 }
659 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100660 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200661 goto error;
662 }
Radek Krejciaf351422015-06-19 14:49:38 +0200663 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200665 break;
666
Radek Krejcif2860132015-06-20 12:37:20 +0200667 case LY_TYPE_BINARY:
668 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200669 case LY_TYPE_INT8:
670 case LY_TYPE_INT16:
671 case LY_TYPE_INT32:
672 case LY_TYPE_INT64:
673 case LY_TYPE_UINT8:
674 case LY_TYPE_UINT16:
675 case LY_TYPE_UINT32:
676 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200677 /* RFC 6020 9.2.4 - range */
678
679 /* length and range are actually the same restriction, so process
680 * them by this common code, we just need to differ the name and
681 * structure where the information will be stored
682 */
683 if (type->base == LY_TYPE_BINARY) {
684 restr = &type->info.binary.length;
685 name = "length";
686 } else {
687 restr = &type->info.num.range;
688 name = "range";
689 }
690
Radek Krejci73adb602015-07-02 18:07:40 +0200691 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200692 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
693 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200694 continue;
695 }
696
Radek Krejcif2860132015-06-20 12:37:20 +0200697 if (!strcmp(node->name, name)) {
698 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100699 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200700 goto error;
701 }
702
703 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200704 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100705 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200706 goto error;
707 }
708 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100709 if (!(*restr)) {
710 LOGMEM;
711 goto error;
712 }
Radek Krejcif2860132015-06-20 12:37:20 +0200713 (*restr)->expr = lydict_insert(module->ctx, value, 0);
714
715 /* get possible substatements */
716 if (read_restr_substmt(module->ctx, *restr, node)) {
717 goto error;
718 }
719 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100720 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200721 goto error;
722 }
Radek Krejcif2860132015-06-20 12:37:20 +0200723 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200724 break;
725
726 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200727 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200728 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200729 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
730 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200731 continue;
732 }
733
Michal Vasko88c29542015-11-27 14:57:53 +0100734 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200735 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100736 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200737 goto error;
738 }
739
740 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200741 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100742 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200743 if (!type->info.lref.path) {
744 goto error;
745 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100746 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200747 goto error;
748 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200749
Radek Krejcidc4c1412015-06-19 15:39:54 +0200750 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100751 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200752 goto error;
753 }
Radek Krejci73adb602015-07-02 18:07:40 +0200754 }
755
Michal Vasko88c29542015-11-27 14:57:53 +0100756 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100757 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200758 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200759 } else if (type->der->type.der && parent) {
760 for (type_der = &type->der->type; !type_der->info.lref.path && type_der->der; type_der = &type_der->der->type);
761 assert(type_der->info.lref.path && type_der->info.lref.target);
762 /* add pointer to leafref target, only on leaves (not in typedefs) */
763 if (lys_leaf_add_leafref_target(type_der->info.lref.target, (struct lys_node *)type->parent)) {
764 goto error;
765 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200766 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200767 break;
768
769 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200770 /* RFC 6020 9.4.4 - length */
771 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200772 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200773 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200774 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
775 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100776 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200777 continue;
778 }
779
Radek Krejci3733a802015-06-19 13:43:21 +0200780 if (!strcmp(node->name, "length")) {
781 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100782 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200783 goto error;
784 }
785
786 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200787 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100788 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200789 goto error;
790 }
791 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100792 if (!type->info.str.length) {
793 LOGMEM;
794 goto error;
795 }
Radek Krejci3733a802015-06-19 13:43:21 +0200796 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
797
Radek Krejci5fbc9162015-06-19 14:11:11 +0200798 /* get possible sub-statements */
799 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200800 goto error;
801 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100802 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200803 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200804 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200805 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100806 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200807 goto error;
808 }
809 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200810 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200811 if (i) {
812 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100813 if (!type->info.str.patterns) {
814 LOGMEM;
815 goto error;
816 }
Radek Krejci73adb602015-07-02 18:07:40 +0200817 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100818 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200819
820 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200821 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
822 if (!precomp) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100823 LOGVAL(LYE_INREGEX, LY_VLOG_NONE, NULL, value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200824 free(type->info.str.patterns);
825 goto error;
826 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200827 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200828
Radek Krejci73adb602015-07-02 18:07:40 +0200829 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200830
831 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100832 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200833 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200834 goto error;
835 }
Radek Krejci73adb602015-07-02 18:07:40 +0200836 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200837 }
838 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200839 break;
840
841 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200842 /* RFC 6020 7.4 - type */
843 /* count number of types in union */
844 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200845 LY_TREE_FOR_SAFE(yin->child, next, node) {
846 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
847 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100848 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200849 continue;
850 }
851
Radek Krejcie4c366b2015-07-02 10:11:31 +0200852 if (!strcmp(node->name, "type")) {
853 i++;
854 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100855 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200856 goto error;
857 }
858 }
859
860 if (!i) {
861 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100862 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200863 break;
864 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100865 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200866 goto error;
867 }
868
869 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200870 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100871 if (!type->info.uni.types) {
872 LOGMEM;
873 goto error;
874 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200875 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200876 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100877 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100878 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
879 if (!rc) {
880 type->info.uni.count++;
881
882 /* union's type cannot be empty or leafref */
883 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100884 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100885 rc = -1;
886 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100887 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100888 rc = -1;
889 }
890 }
891 if (rc) {
892 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
893 for (i = 0; i < type->info.uni.count; ++i) {
894 lys_type_free(module->ctx, &type->info.uni.types[i]);
895 }
896 free(type->info.uni.types);
897 type->info.uni.types = NULL;
898 type->info.uni.count = 0;
899
900 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100901 ret = EXIT_FAILURE;
902 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100903 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200904 goto error;
905 }
Michal Vasko88c29542015-11-27 14:57:53 +0100906 }
907 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200908
Michal Vasko88c29542015-11-27 14:57:53 +0100909 case LY_TYPE_BOOL:
910 case LY_TYPE_EMPTY:
911 /* no sub-statement allowed */
912 LY_TREE_FOR(yin->child, node) {
913 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100914 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200915 goto error;
916 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200917 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200918 break;
919
920 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100921 LOGINT;
922 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200923 }
924
925 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200926
927error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100928 if (type->module_name) {
929 lydict_remove(module->ctx, type->module_name);
930 type->module_name = NULL;
931 }
932 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200933}
934
Michal Vasko0d343d12015-08-24 14:57:36 +0200935/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200937fill_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 +0200938{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100940 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100941 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100944 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200945 goto error;
946 }
947 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200949 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100950 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 goto error;
952 }
Radek Krejcieac35532015-05-31 19:09:15 +0200953
Michal Vasko88c29542015-11-27 14:57:53 +0100954 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200955 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
956 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200957 continue;
958 }
959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100961 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100962 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 goto error;
964 }
Michal Vasko88c29542015-11-27 14:57:53 +0100965 /* HACK for unres */
966 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100967 tpdf->type.parent = tpdf;
Radek Krejci48464ed2016-03-17 15:44:09 +0100968 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent)) {
Radek Krejci73adb602015-07-02 18:07:40 +0200969 goto error;
970 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200971 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 } else if (!strcmp(node->name, "default")) {
973 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100974 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 goto error;
976 }
977 GETVAL(value, node, "value");
978 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
979 } else if (!strcmp(node->name, "units")) {
980 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100981 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 goto error;
983 }
984 GETVAL(value, node, "name");
985 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
986 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100987 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200988 goto error;
989 }
990 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200993 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100994 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 goto error;
996 }
Radek Krejcieac35532015-05-31 19:09:15 +0200997
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200998 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200999 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001000 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001001 goto error;
1002 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001005 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001006
1007error:
1008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001010}
1011
Michal Vasko0d343d12015-08-24 14:57:36 +02001012/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001013static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001014fill_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 +02001015{
1016 const char *value;
1017 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001018 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001019
Radek Krejcib05774c2015-06-18 13:52:59 +02001020 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001021 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001022 goto error;
1023 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001024 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001025 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001026
Radek Krejci76512572015-08-04 09:47:08 +02001027 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001028 goto error;
1029 }
1030
1031 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001032 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1033 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001034 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001035 continue;
1036 }
1037
Radek Krejci3cf9e222015-06-18 11:37:50 +02001038 if (!strcmp(child->name, "if-feature")) {
1039 c++;
1040 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001041 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001042 goto error;
1043 }
1044 }
1045
1046 if (c) {
1047 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001048 if (!f->features) {
1049 LOGMEM;
1050 goto error;
1051 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001052 }
Radek Krejci73adb602015-07-02 18:07:40 +02001053 LY_TREE_FOR(yin->child, child) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001054 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001055 f->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001056 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001057 goto error;
1058 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001059 }
1060
Radek Krejci3cf9e222015-06-18 11:37:50 +02001061 return EXIT_SUCCESS;
1062
1063error:
1064
1065 return EXIT_FAILURE;
1066}
1067
Michal Vasko0d343d12015-08-24 14:57:36 +02001068/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069static int
Radek Krejcib8048692015-08-05 13:36:34 +02001070fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001071{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001075 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001076 if (!must->expr) {
1077 goto error;
1078 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001079 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001080 goto error;
1081 }
Radek Krejci800af702015-06-02 13:46:01 +02001082
Radek Krejci41726f92015-06-19 13:11:05 +02001083 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001084
Michal Vasko77dc5652016-02-15 12:32:42 +01001085error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001087}
1088
Radek Krejci581ce772015-11-10 17:22:40 +01001089static int
Michal Vasko88c29542015-11-27 14:57:53 +01001090fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1091 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001092{
1093 int i, j;
1094 const char *value, *vaux;
1095
1096 /* get unique value (list of leafs supposed to be unique */
1097 GETVAL(value, yin, "tag");
1098
1099 /* count the number of unique leafs in the value */
1100 vaux = value;
1101 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001102 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001103 while (isspace(*vaux)) {
1104 vaux++;
1105 }
1106 }
1107 unique->expr_size++;
1108 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001109 if (!unique->expr) {
1110 LOGMEM;
1111 goto error;
1112 }
Radek Krejci581ce772015-11-10 17:22:40 +01001113
1114 for (i = 0; i < unique->expr_size; i++) {
1115 vaux = strpbrk(value, " \t\n");
1116 if (!vaux) {
1117 /* the last token, lydict_insert() will count its size on its own */
1118 vaux = value;
1119 }
1120
1121 /* store token into unique structure */
1122 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1123
1124 /* check that the expression does not repeat */
1125 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001126 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001127 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1128 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001129 goto error;
1130 }
1131 }
1132
1133 /* try to resolve leaf */
1134 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001135 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1136 goto error;
1137 }
Radek Krejci581ce772015-11-10 17:22:40 +01001138 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001139 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001140 goto error;
1141 }
1142 }
1143
1144 /* move to next token */
1145 value = vaux;
1146 while(isspace(*value)) {
1147 value++;
1148 }
1149 }
1150
1151 return EXIT_SUCCESS;
1152
1153error:
1154 return EXIT_FAILURE;
1155}
1156
Michal Vasko0d343d12015-08-24 14:57:36 +02001157/* logs directly
1158 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001159 * type: 0 - min, 1 - max
1160 */
1161static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001162deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001163{
1164 const char *value;
1165 char *endptr;
1166 unsigned long val;
1167 uint32_t *ui32val;
1168
Michal Vaskof7e57d52016-03-07 11:31:09 +01001169 /* del min/max is forbidden */
1170 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001171 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001172 goto error;
1173 }
1174
Radek Krejcieb00f512015-07-01 16:44:58 +02001175 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001176 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001177 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001178 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001179 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001180 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001181 }
Radek Krejci76512572015-08-04 09:47:08 +02001182 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001183 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001184 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001185 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001186 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001187 }
1188 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001189 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1190 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001191 goto error;
1192 }
1193
1194 GETVAL(value, node, "value");
1195 while (isspace(value[0])) {
1196 value++;
1197 }
1198
Radek Krejci0d7b2472016-02-12 11:11:03 +01001199 if (type && !strcmp(value, "unbounded")) {
1200 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001201 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001202 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001203 /* convert it to uint32_t */
1204 errno = 0;
1205 endptr = NULL;
1206 val = strtoul(value, &endptr, 10);
1207 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001208 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001209 goto error;
1210 }
1211 if (type) {
1212 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001213 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001214 } else {
1215 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001216 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001217 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001218 }
1219
1220 if (d->mod == LY_DEVIATE_ADD) {
1221 /* check that there is no current value */
1222 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001223 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1224 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001225 goto error;
1226 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001227 } else if (d->mod == LY_DEVIATE_RPL) {
1228 /* unfortunately, there is no way to check reliably that there
1229 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001230 }
1231
Michal Vaskof7e57d52016-03-07 11:31:09 +01001232 /* add (already checked) and replace */
1233 /* set new value specified in deviation */
1234 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001235
1236 return EXIT_SUCCESS;
1237
1238error:
1239
1240 return EXIT_FAILURE;
1241}
1242
Michal Vasko0d343d12015-08-24 14:57:36 +02001243/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001244static int
Michal Vasko88c29542015-11-27 14:57:53 +01001245fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1246 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001247{
1248 const char *value, **stritem;
1249 struct lyxml_elem *next, *child, *develem;
1250 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001251 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001252 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001253 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001254 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001255 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001256 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001257 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001258 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001259 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001260 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001261 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001262 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001263
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001264 ctx = module->ctx;
1265
Radek Krejcieb00f512015-07-01 16:44:58 +02001266 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001267 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001268 if (!dev->target_name) {
1269 goto error;
1270 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001271
1272 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001273 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1274 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001275 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001276 goto error;
1277 }
Radek Krejcic4283442016-04-22 09:19:27 +02001278 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001279 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1280 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001281 goto error;
1282 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001283 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001284
1285 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001286 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1287 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001288 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001289 continue;
1290 }
1291
Radek Krejcieb00f512015-07-01 16:44:58 +02001292 if (!strcmp(child->name, "description")) {
1293 if (dev->dsc) {
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->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001298 if (!dev->dsc) {
1299 goto error;
1300 }
1301 } else if (!strcmp(child->name, "reference")) {
1302 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001303 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001304 goto error;
1305 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001306 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001307 if (!dev->ref) {
1308 goto error;
1309 }
1310 } else if (!strcmp(child->name, "deviate")) {
1311 c_dev++;
1312
Michal Vasko345da0a2015-12-02 10:35:55 +01001313 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001314 * further processed later
1315 */
1316 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001317
Radek Krejcieb00f512015-07-01 16:44:58 +02001318 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001319 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001320 goto error;
1321 }
1322
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001323 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001324 }
1325
1326 if (c_dev) {
1327 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001328 if (!dev->deviate) {
1329 LOGMEM;
1330 goto error;
1331 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001332 }
1333
1334 LY_TREE_FOR(yin->child, develem) {
1335 /* init */
1336 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001337 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001338 c_must = 0;
1339 c_uniq = 0;
1340
1341 /* get deviation type */
1342 GETVAL(value, develem, "value");
1343 if (!strcmp(value, "not-supported")) {
1344 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1345 /* no property expected in this case */
1346 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001347 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001348 goto error;
1349 }
1350
Radek Krejci5b917642015-07-02 09:03:13 +02001351 /* and neither any other deviate statement is expected,
1352 * not-supported deviation must be the only deviation of the target
1353 */
1354 if (dev->deviate_size || develem->next) {
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 be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001357 goto error;
1358 }
1359
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001360 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001361 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1362 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1363 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001364 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1365 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001366 goto error;
1367 }
1368 }
1369 }
Radek Krejci5b917642015-07-02 09:03:13 +02001370
Michal Vaskoff006c12016-02-17 11:15:19 +01001371 /* unlink and store the original node */
1372 lys_node_unlink(dev_target);
1373 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001374
Radek Krejci5b917642015-07-02 09:03:13 +02001375 dev->deviate_size = 1;
1376 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001377 } else if (!strcmp(value, "add")) {
1378 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1379 } else if (!strcmp(value, "replace")) {
1380 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1381 } else if (!strcmp(value, "delete")) {
1382 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1383 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001384 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001385 goto error;
1386 }
1387 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001388 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001389
Michal Vaskoff006c12016-02-17 11:15:19 +01001390 /* store a shallow copy of the original node */
1391 if (!dev->orig_node) {
1392 memset(&tmp_unres, 0, sizeof tmp_unres);
1393 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1394 /* just to be safe */
1395 if (tmp_unres.count) {
1396 LOGINT;
1397 goto error;
1398 }
1399 }
1400
Radek Krejcieb00f512015-07-01 16:44:58 +02001401 /* process deviation properties */
1402 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001403 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1404 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001405 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001406 continue;
1407 }
1408
Radek Krejcieb00f512015-07-01 16:44:58 +02001409 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001410 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001411 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001412 goto error;
1413 }
1414
1415 /* for we deviate from RFC 6020 and allow config property even it is/is not
1416 * specified in the target explicitly since config property inherits. So we expect
1417 * that config is specified in every node. But for delete, we check that the value
1418 * is the same as here in deviation
1419 */
1420 GETVAL(value, child, "value");
1421 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001422 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001423 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001424 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001425 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001426 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001427 goto error;
1428 }
1429
1430 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001431 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001432 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001433 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001434 } else { /* add and replace are the same in this case */
1435 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001436 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001437
1438 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001439 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001440 }
1441 } else if (!strcmp(child->name, "default")) {
1442 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001443 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001444 goto error;
1445 }
1446 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001447 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001448
Michal Vasko60f4b452016-02-12 11:02:55 +01001449 if (dev_target->nodetype == LYS_CHOICE) {
1450 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001451
1452 if (d->mod == LY_DEVIATE_ADD) {
1453 /* check that there is no current value */
1454 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001455 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1456 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001457 goto error;
1458 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001459 /* check collision with mandatory */
1460 if (choice->flags & LYS_MAND_TRUE) {
1461 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1462 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1463 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1464 goto error;
1465 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001466 } else if (d->mod == LY_DEVIATE_RPL) {
1467 /* check that there was a value before */
1468 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001469 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1470 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001471 goto error;
1472 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001473 }
1474
Michal Vasko3edeaf72016-02-11 13:17:43 +01001475 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001476 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001477 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001478 goto error;
1479 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001480 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001481 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001482 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1483 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001484 goto error;
1485 }
1486 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001487 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001488 if (!choice->dflt) {
1489 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001490 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001491 goto error;
1492 }
1493 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001494 } else if (dev_target->nodetype == LYS_LEAF) {
1495 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001496
1497 if (d->mod == LY_DEVIATE_ADD) {
1498 /* check that there is no current value */
1499 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001500 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1501 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
Radek Krejci841ec082016-04-05 13:05:17 +02001504 /* check collision with mandatory */
1505 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001506 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001507 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001508 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001509 goto error;
1510 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001511 }
1512
1513 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001514 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001515 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1516 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001517 goto error;
1518 }
1519 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001520 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001521 leaf->dflt = NULL;
1522 } else { /* add (already checked) and replace */
1523 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001524 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001525
1526 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001527 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001528
1529 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1530 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1531 if (!leaf_dflt_check) {
1532 LOGMEM;
1533 goto error;
1534 }
1535 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001536 }
1537 } else {
1538 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001539 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1540 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001541 goto error;
1542 }
1543 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001544 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001545 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001546 goto error;
1547 }
1548
1549 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001550 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001551 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1552 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001553 goto error;
1554 }
1555
1556 GETVAL(value, child, "value");
1557 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001558 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001559 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001560 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001561 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001562 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 goto error;
1564 }
1565
1566 if (d->mod == LY_DEVIATE_ADD) {
1567 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001568 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001569 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1570 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001571 goto error;
1572 }
Radek Krejci841ec082016-04-05 13:05:17 +02001573 /* check collision with default-stmt */
1574 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001575 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001576 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001577 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001578 goto error;
1579 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001580
Michal Vasko21be1b32016-03-07 12:31:34 +01001581 dev_target->flags |= d->flags & LYS_MAND_MASK;
1582 } else if (d->mod == LY_DEVIATE_RPL) {
1583 /* check that there was a value before */
1584 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001585 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1586 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 goto error;
1588 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001589
Michal Vasko21be1b32016-03-07 12:31:34 +01001590 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001591 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001592 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001593 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001594 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001595 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001596 }
1597 } else if (!strcmp(child->name, "min-elements")) {
1598 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001599 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001600 goto error;
1601 }
1602 f_min = 1;
1603
Michal Vasko60f4b452016-02-12 11:02:55 +01001604 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001605 goto error;
1606 }
1607 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001608 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001609 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001610 goto error;
1611 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001612 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001613
Michal Vasko60f4b452016-02-12 11:02:55 +01001614 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001615 goto error;
1616 }
1617 } else if (!strcmp(child->name, "must")) {
1618 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001619 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001620 continue;
1621 } else if (!strcmp(child->name, "type")) {
1622 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001623 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001624 goto error;
1625 }
1626
Michal Vaskof7e57d52016-03-07 11:31:09 +01001627 /* add, del type is forbidden */
1628 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001629 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001630 goto error;
1631 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001632 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001633 goto error;
1634 }
1635
Radek Krejcieb00f512015-07-01 16:44:58 +02001636 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001637 if (dev_target->nodetype == LYS_LEAF) {
1638 t = &((struct lys_node_leaf *)dev_target)->type;
1639 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1640 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001642 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1643 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 goto error;
1645 }
1646
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001648 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001649 /* HACK for unres */
1650 t->der = (struct lys_tpdf *)child;
Radek Krejci48464ed2016-03-17 15:44:09 +01001651 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001652 goto error;
1653 }
1654 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001655
1656 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1657 if (dev_target->nodetype == LYS_LEAF) {
1658 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1659 if (!leaf_dflt_check) {
1660 LOGMEM;
1661 goto error;
1662 }
1663 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1664 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 } else if (!strcmp(child->name, "unique")) {
1666 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001667 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001668 continue;
1669 } else if (!strcmp(child->name, "units")) {
1670 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001671 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001672 goto error;
1673 }
1674
1675 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001676 if (dev_target->nodetype == LYS_LEAFLIST) {
1677 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1678 } else if (dev_target->nodetype == LYS_LEAF) {
1679 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001680 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001681 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1682 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001683 goto error;
1684 }
1685
1686 /* get units value */
1687 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001688 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001689
1690 /* apply to target */
1691 if (d->mod == LY_DEVIATE_ADD) {
1692 /* check that there is no current value */
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, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001696 goto error;
1697 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001698
Michal Vasko21be1b32016-03-07 12:31:34 +01001699 *stritem = lydict_insert(ctx, value, 0);
1700 } else if (d->mod == LY_DEVIATE_RPL) {
1701 /* check that there was a value before */
1702 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001703 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1704 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001705 goto error;
1706 }
1707
1708 lydict_remove(ctx, *stritem);
1709 *stritem = lydict_insert(ctx, value, 0);
1710 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001711 /* check values */
1712 if (*stritem != d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001713 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1714 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001715 goto error;
1716 }
1717 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001718 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001719 }
1720 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001722 goto error;
1723 }
1724
Michal Vasko88c29542015-11-27 14:57:53 +01001725 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001726 }
1727
1728 if (c_must) {
1729 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001730 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001731 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001732 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1733 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001734 break;
Radek Krejci76512572015-08-04 09:47:08 +02001735 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001736 trg_must = &((struct lys_node_container *)dev_target)->must;
1737 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 break;
Radek Krejci76512572015-08-04 09:47:08 +02001739 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001740 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1741 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001742 break;
Radek Krejci76512572015-08-04 09:47:08 +02001743 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001744 trg_must = &((struct lys_node_list *)dev_target)->must;
1745 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 break;
Radek Krejci76512572015-08-04 09:47:08 +02001747 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001748 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1749 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001750 break;
1751 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001752 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1753 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001754 goto error;
1755 }
1756
1757 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001758 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001759 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001760 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 } else if (d->mod == LY_DEVIATE_ADD) {
1762 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001763 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001764 if (!d->must) {
1765 LOGMEM;
1766 goto error;
1767 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001768 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001769 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001770 d->must_size = c_must;
1771 } else { /* LY_DEVIATE_DEL */
1772 d->must = calloc(c_must, sizeof *d->must);
1773 }
Michal Vasko253035f2015-12-17 16:58:13 +01001774 if (!d->must) {
1775 LOGMEM;
1776 goto error;
1777 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001778 }
1779 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001780 /* replace unique is forbidden */
1781 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001782 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001783 goto error;
1784 }
1785
Radek Krejcieb00f512015-07-01 16:44:58 +02001786 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001787 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001788 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1789 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 goto error;
1791 }
1792
Michal Vasko60f4b452016-02-12 11:02:55 +01001793 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001794 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001796 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001797 list->unique = d->unique;
1798 d->unique = &list->unique[list->unique_size];
1799 d->unique_size = c_uniq;
1800 } else { /* LY_DEVIATE_DEL */
1801 d->unique = calloc(c_uniq, sizeof *d->unique);
1802 }
Michal Vasko253035f2015-12-17 16:58:13 +01001803 if (!d->unique) {
1804 LOGMEM;
1805 goto error;
1806 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 }
1808
1809 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001810 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 if (!strcmp(child->name, "must")) {
1812 if (d->mod == LY_DEVIATE_DEL) {
1813 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1814 goto error;
1815 }
1816
1817 /* find must to delete, we are ok with just matching conditions */
1818 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001819 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001820 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001821 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001822 /* ... and maintain the array */
1823 (*trg_must_size)--;
1824 if (i != *trg_must_size) {
1825 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1826 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1827 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1828 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1829 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1830 }
1831 if (!(*trg_must_size)) {
1832 free(*trg_must);
1833 *trg_must = NULL;
1834 } else {
1835 (*trg_must)[*trg_must_size].expr = NULL;
1836 (*trg_must)[*trg_must_size].dsc = NULL;
1837 (*trg_must)[*trg_must_size].ref = NULL;
1838 (*trg_must)[*trg_must_size].eapptag = NULL;
1839 (*trg_must)[*trg_must_size].emsg = NULL;
1840 }
1841
1842 i = -1; /* set match flag */
1843 break;
1844 }
1845 }
1846 d->must_size++;
1847 if (i != -1) {
1848 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001849 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001850 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001851 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 goto error;
1853 }
1854 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001855 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1856 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 goto error;
1858 }
1859 (*trg_must_size)++;
1860 }
1861 } else if (!strcmp(child->name, "unique")) {
1862 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001863 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001864 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001865 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001866 goto error;
1867 }
1868
1869 /* find unique structures to delete */
1870 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001871 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001872 continue;
1873 }
1874
Radek Krejci581ce772015-11-10 17:22:40 +01001875 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001876 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001877 break;
1878 }
1879 }
1880
Radek Krejci581ce772015-11-10 17:22:40 +01001881 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001882 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001883 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001884 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001885 }
1886 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001887 /* ... and maintain the array */
1888 list->unique_size--;
1889 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001890 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1891 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001892 }
1893
1894 if (!list->unique_size) {
1895 free(list->unique);
1896 list->unique = NULL;
1897 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001898 list->unique[list->unique_size].expr_size = 0;
1899 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001900 }
1901
1902 i = -1; /* set match flag */
1903 break;
1904 }
1905 }
1906
1907 d->unique_size++;
1908 if (i != -1) {
1909 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001910 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1911 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001912 goto error;
1913 }
1914 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001915 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001916 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001917 list->unique_size++;
1918 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001919 goto error;
1920 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001921 }
1922 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 }
1924 }
1925
Michal Vasko43a1feb2016-03-07 12:03:02 +01001926 /* now check whether default value, if any, matches the type */
1927 for (i = 0; i < leaf_dflt_check_count; ++i) {
1928 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001929 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 +01001930 if (rc == -1) {
1931 goto error;
1932 } else if (rc == EXIT_FAILURE) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001933 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1934 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 +01001935 goto error;
1936 }
1937 }
1938 }
1939 free(leaf_dflt_check);
1940
Radek Krejcieb00f512015-07-01 16:44:58 +02001941 return EXIT_SUCCESS;
1942
1943error:
Michal Vasko34867132016-03-11 10:26:38 +01001944 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001945 return EXIT_FAILURE;
1946}
1947
Michal Vasko0d343d12015-08-24 14:57:36 +02001948/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001949static int
Radek Krejcib8048692015-08-05 13:36:34 +02001950fill_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 +02001951 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001952{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001954 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001956 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001957
Michal Vasko591e0b22015-08-13 13:53:43 +02001958 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001960 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02001961 if (!aug->target_name) {
1962 goto error;
1963 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001964 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001965
Michal Vasko1d87a922015-08-21 12:57:16 +02001966 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001967 goto error;
1968 }
1969
1970 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001971 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1972 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001973 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001974 continue;
1975 }
1976
Radek Krejci3cf9e222015-06-18 11:37:50 +02001977 if (!strcmp(child->name, "if-feature")) {
1978 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001979 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001980 } else if (!strcmp(child->name, "when")) {
1981 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001982 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001983 goto error;
1984 }
1985
1986 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001987 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001988 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001989 goto error;
1990 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001991 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001992 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001993
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 /* check allowed data sub-statements */
1995 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001998 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002006 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002007 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002008 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002010 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002012 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002013 goto error;
2014 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002015
Radek Krejci1d82ef62015-08-07 14:44:40 +02002016 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017 goto error;
2018 }
2019
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002021 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002022 }
2023
2024 if (c) {
2025 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002026 if (!aug->features) {
2027 LOGMEM;
2028 goto error;
2029 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002030 }
2031
2032 LY_TREE_FOR_SAFE(yin->child, next, child) {
2033 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002034 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002035 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002036 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002037 goto error;
2038 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002039 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002040 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002041 }
2042
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002043 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002044 * connected to the tree and adjusted (if possible right now).
2045 * However, if this is augment in a uses, it gets resolved
2046 * when the uses does and cannot be resolved now for sure
2047 * (the grouping was not yet copied into uses).
2048 */
2049 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002050 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002051 goto error;
2052 }
Michal Vasko49291b32015-08-06 09:49:41 +02002053 }
Radek Krejci106efc02015-06-10 14:36:27 +02002054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002056
2057error:
2058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002060}
2061
Michal Vasko0d343d12015-08-24 14:57:36 +02002062/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063static int
Michal Vasko0d204592015-10-07 09:50:04 +02002064fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002065{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 struct lyxml_elem *sub, *next;
2067 const char *value;
2068 char *endptr;
2069 int f_mand = 0, f_min = 0, f_max = 0;
2070 int c_must = 0;
2071 int r;
2072 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002073
Radek Krejci76512572015-08-04 09:47:08 +02002074 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 goto error;
2076 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002077
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002078 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002079 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002080 if (!rfn->target_name) {
2081 goto error;
2082 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002085 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2086 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002087 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002088 continue;
2089 }
2090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 /* limited applicability */
2092 if (!strcmp(sub->name, "default")) {
2093 /* leaf or choice */
2094 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002095 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 goto error;
2097 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 /* check possibility of statements combination */
2100 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002101 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002103 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2104 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 goto error;
2106 }
2107 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002108 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 GETVAL(value, sub, "value");
2112 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2113 } else if (!strcmp(sub->name, "mandatory")) {
2114 /* leaf, choice or anyxml */
2115 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002116 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 goto error;
2118 }
2119 /* just checking the flags in leaf is not sufficient, we would allow
2120 * multiple mandatory statements with the "false" value
2121 */
2122 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 /* check possibility of statements combination */
2125 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002126 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002128 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2129 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 goto error;
2131 }
2132 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002133 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 GETVAL(value, sub, "value");
2137 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002138 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002140 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002142 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 goto error;
2144 }
2145 } else if (!strcmp(sub->name, "min-elements")) {
2146 /* list or leaf-list */
2147 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002148 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 goto error;
2150 }
2151 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 /* check possibility of statements combination */
2154 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002155 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002157 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2158 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 goto error;
2160 }
2161 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002162 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 GETVAL(value, sub, "value");
2166 while (isspace(value[0])) {
2167 value++;
2168 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 /* convert it to uint32_t */
2171 errno = 0;
2172 endptr = NULL;
2173 val = strtoul(value, &endptr, 10);
2174 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002175 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 goto error;
2177 }
2178 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002179 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 } else if (!strcmp(sub->name, "max-elements")) {
2181 /* list or leaf-list */
2182 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002183 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 goto error;
2185 }
2186 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 /* check possibility of statements combination */
2189 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002190 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002192 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2193 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 goto error;
2195 }
2196 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002197 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 GETVAL(value, sub, "value");
2201 while (isspace(value[0])) {
2202 value++;
2203 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002204
Radek Krejci0d7b2472016-02-12 11:11:03 +01002205 if (!strcmp(value, "unbounded")) {
2206 rfn->mod.list.max = 0;
2207 } else {
2208 /* convert it to uint32_t */
2209 errno = 0;
2210 endptr = NULL;
2211 val = strtoul(value, &endptr, 10);
2212 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002213 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002214 goto error;
2215 }
2216 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002218 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 } else if (!strcmp(sub->name, "presence")) {
2220 /* container */
2221 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002222 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 goto error;
2224 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 /* check possibility of statements combination */
2227 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002228 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002230 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2231 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 goto error;
2233 }
2234 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002235 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 GETVAL(value, sub, "value");
2239 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2240 } else if (!strcmp(sub->name, "must")) {
2241 /* leaf-list, list, container or anyxml */
2242 /* check possibility of statements combination */
2243 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002244 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002246 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2247 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 goto error;
2249 }
2250 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002251 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002255 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002258 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 goto error;
2260 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002261
Michal Vasko345da0a2015-12-02 10:35:55 +01002262 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 /* process nodes with cardinality of 0..n */
2266 if (c_must) {
2267 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002268 if (!rfn->must) {
2269 LOGMEM;
2270 goto error;
2271 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 }
Radek Krejci73adb602015-07-02 18:07:40 +02002273 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002274 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2275 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002276 if (r) {
2277 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002282
2283error:
2284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002286}
2287
Michal Vasko0d343d12015-08-24 14:57:36 +02002288/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289static int
Radek Krejcib8048692015-08-05 13:36:34 +02002290fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002291{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 struct lyxml_elem *child;
2293 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002296 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2297 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002298 continue;
2299 }
2300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 if (!strcmp(child->name, "prefix")) {
2302 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002303 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 goto error;
2305 }
2306 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2307 } else if (!strcmp(child->name, "revision-date")) {
2308 if (imp->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002309 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 goto error;
2311 }
2312 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002313 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 goto error;
2315 }
2316 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2317 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002318 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 goto error;
2320 }
2321 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 /* check mandatory information */
2324 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002325 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 goto error;
2327 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002330
Pavol Vicane994fda2016-03-22 10:47:58 +01002331 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002332
2333error:
2334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002336}
2337
Michal Vasko0d343d12015-08-24 14:57:36 +02002338/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002339static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002340fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2341 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002342{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 struct lyxml_elem *child;
2344 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002347 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2348 /* garbage */
2349 continue;
2350 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 if (!strcmp(child->name, "revision-date")) {
2352 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002353 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 goto error;
2355 }
2356 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002357 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 goto error;
2359 }
2360 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2361 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002362 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363 goto error;
2364 }
2365 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002368
Pavol Vican0adf01d2016-03-22 12:29:33 +01002369 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002370
2371error:
2372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002374}
2375
Michal Vasko0d343d12015-08-24 14:57:36 +02002376/* logs directly
2377 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002378 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002379 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002380 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002381 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002382static int
Radek Krejcib8048692015-08-05 13:36:34 +02002383read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002384 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002385{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002386 const char *value;
2387 struct lyxml_elem *sub, *next;
2388 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002390 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002391 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002392 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 if (opt & OPT_IDENT) {
2395 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002396 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 goto error;
2398 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002399 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002400 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002401
Radek Krejci6764bb32015-07-03 15:16:04 +02002402 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002403 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002404 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002405 }
2406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002407 /* process local parameters */
2408 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002409 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002410 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002411 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002412 continue;
2413 }
2414 if (strcmp(sub->ns->value, LY_NSYIN)) {
2415 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002416 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002417 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002418 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002419 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002420 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002421 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002422 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002423 goto error;
2424 }
2425 }
2426
2427 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002428 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002429 continue;
2430 }
2431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002433 if (node->dsc) {
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->dsc = read_yin_subnode(ctx, sub, "text");
2438 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002439 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002440 }
2441 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002442 if (node->ref) {
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 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002446 node->ref = read_yin_subnode(ctx, sub, "text");
2447 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002448 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 }
2450 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002451 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002452 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 goto error;
2454 }
2455 GETVAL(value, sub, "value");
2456 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002457 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002461 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002463 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002464 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 }
2466 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002467 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002468 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002469 goto error;
2470 }
2471 GETVAL(value, sub, "value");
2472 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002473 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002474 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002475 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002477 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002478 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002479 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002480 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002482 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 continue;
2484 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002485 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002487
Radek Krejci1d82ef62015-08-07 14:44:40 +02002488 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002490 if (parent && (parent->flags & LYS_CONFIG_R)) {
2491 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 } else {
2493 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002494 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 }
2496 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002498 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002499
2500error:
2501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002502 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002503}
2504
Michal Vasko0d343d12015-08-24 14:57:36 +02002505/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002506static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002507read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002508{
Radek Krejci76512572015-08-04 09:47:08 +02002509 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002510 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002511 const char *value;
2512
2513 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002514 if (!retval) {
2515 LOGMEM;
2516 return NULL;
2517 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002518
2519 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002520 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002521 if (!retval->cond) {
2522 goto error;
2523 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002524 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002525 goto error;
2526 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002527
Radek Krejci73adb602015-07-02 18:07:40 +02002528 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002529 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2530 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002531 continue;
2532 }
2533
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002534 if (!strcmp(child->name, "description")) {
2535 if (retval->dsc) {
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->dsc = read_yin_subnode(module->ctx, child, "text");
2540 if (!retval->dsc) {
2541 goto error;
2542 }
2543 } else if (!strcmp(child->name, "reference")) {
2544 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002545 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002546 goto error;
2547 }
2548 retval->ref = read_yin_subnode(module->ctx, child, "text");
2549 if (!retval->ref) {
2550 goto error;
2551 }
2552 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002553 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002554 goto error;
2555 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002556 }
2557
2558 return retval;
2559
2560error:
2561
Michal Vasko0308dd62015-10-07 09:14:40 +02002562 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002563 return NULL;
2564}
2565
Michal Vasko0d343d12015-08-24 14:57:36 +02002566/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002567static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002568read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2569 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002570{
Michal Vasko29fc0182015-08-24 15:02:39 +02002571 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002572 struct lys_node_case *cs;
2573 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002574 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002575
Radek Krejcie867c852015-08-27 09:52:34 +02002576 /* init */
2577 memset(&root, 0, sizeof root);
2578
Radek Krejci1d82ef62015-08-07 14:44:40 +02002579 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002580 if (!cs) {
2581 LOGMEM;
2582 return NULL;
2583 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002584 cs->nodetype = LYS_CASE;
2585 cs->prev = (struct lys_node *)cs;
2586 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002587
Radek Krejci6a113852015-07-03 16:04:20 +02002588 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002589 goto error;
2590 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002591
Radek Krejcia9544502015-08-14 08:24:29 +02002592 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2593
Michal Vasko3a0043f2015-08-12 12:11:30 +02002594 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002595 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002596 goto error;
2597 }
2598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002599 /* process choice's specific children */
2600 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002601 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2602 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002603 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002604 continue;
2605 }
2606
Michal Vasko29fc0182015-08-24 15:02:39 +02002607 if (!strcmp(sub->name, "container") ||
2608 !strcmp(sub->name, "leaf-list") ||
2609 !strcmp(sub->name, "leaf") ||
2610 !strcmp(sub->name, "list") ||
2611 !strcmp(sub->name, "uses") ||
2612 !strcmp(sub->name, "choice") ||
2613 !strcmp(sub->name, "anyxml")) {
2614
Michal Vaskof3930de2015-10-22 12:03:59 +02002615 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002616 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002617 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002618 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002619 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002620 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002621 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002622 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002623 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002624 goto error;
2625 }
2626
Radek Krejci1d82ef62015-08-07 14:44:40 +02002627 cs->when = read_yin_when(module, sub);
2628 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002629 goto error;
2630 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002631
Michal Vasko345da0a2015-12-02 10:35:55 +01002632 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002634 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002635 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002637 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002638
Radek Krejci3cf9e222015-06-18 11:37:50 +02002639 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002640 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002641 if (!cs->features) {
2642 LOGMEM;
2643 goto error;
2644 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002645 }
Radek Krejci73adb602015-07-02 18:07:40 +02002646 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002647 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002648 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002649 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002650 goto error;
2651 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002652 }
Radek Krejcib388c152015-06-04 17:03:03 +02002653
Michal Vasko29fc0182015-08-24 15:02:39 +02002654 /* last part - process data nodes */
2655 LY_TREE_FOR_SAFE(root.child, next, sub) {
2656 if (!strcmp(sub->name, "container")) {
2657 node = read_yin_container(module, retval, sub, resolve, unres);
2658 } else if (!strcmp(sub->name, "leaf-list")) {
2659 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2660 } else if (!strcmp(sub->name, "leaf")) {
2661 node = read_yin_leaf(module, retval, sub, resolve, unres);
2662 } else if (!strcmp(sub->name, "list")) {
2663 node = read_yin_list(module, retval, sub, resolve, unres);
2664 } else if (!strcmp(sub->name, "choice")) {
2665 node = read_yin_choice(module, retval, sub, resolve, unres);
2666 } else if (!strcmp(sub->name, "uses")) {
2667 node = read_yin_uses(module, retval, sub, resolve, unres);
2668 } else if (!strcmp(sub->name, "anyxml")) {
2669 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2670 }
2671 if (!node) {
2672 goto error;
2673 }
2674
Michal Vasko345da0a2015-12-02 10:35:55 +01002675 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002676 }
2677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002679
2680error:
2681
Michal Vasko29fc0182015-08-24 15:02:39 +02002682 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002683 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002684 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002685 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002687 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002688}
2689
Michal Vasko0d343d12015-08-24 14:57:36 +02002690/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002691static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002692read_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 +02002693{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002694 struct lyxml_elem *sub, *next;
2695 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002696 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002697 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002698 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002699 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002701 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002702 if (!choice) {
2703 LOGMEM;
2704 return NULL;
2705 }
Radek Krejci76512572015-08-04 09:47:08 +02002706 choice->nodetype = LYS_CHOICE;
2707 choice->prev = (struct lys_node *)choice;
2708 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002709
Michal Vaskoe0c59842015-09-24 13:52:20 +02002710 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2711 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 goto error;
2713 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002714
Radek Krejcia9544502015-08-14 08:24:29 +02002715 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2716
Michal Vasko3a0043f2015-08-12 12:11:30 +02002717 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002718 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002719 goto error;
2720 }
2721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 /* process choice's specific children */
2723 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002724 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2725 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002726 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002727 continue;
2728 }
2729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002731 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002732 goto error;
2733 }
2734 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002735 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 goto error;
2737 }
2738 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002739 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 goto error;
2741 }
2742 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002743 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002744 goto error;
2745 }
2746 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002747 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 goto error;
2749 }
2750 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002751 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002752 goto error;
2753 }
2754 } else if (!strcmp(sub->name, "default")) {
2755 if (dflt_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002756 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 goto error;
2758 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002759 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002760 } else if (!strcmp(sub->name, "mandatory")) {
2761 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002762 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002763 goto error;
2764 }
2765 /* just checking the flags in leaf is not sufficient, we would allow
2766 * multiple mandatory statements with the "false" value
2767 */
2768 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002770 GETVAL(value, sub, "value");
2771 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002772 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002773 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002774 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002775 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002776 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002777 goto error;
2778 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002779 } else if (!strcmp(sub->name, "when")) {
2780 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002781 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002782 goto error;
2783 }
2784
2785 choice->when = read_yin_when(module, sub);
2786 if (!choice->when) {
2787 goto error;
2788 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002789 } else if (!strcmp(sub->name, "if-feature")) {
2790 c_ftrs++;
2791
Michal Vasko345da0a2015-12-02 10:35:55 +01002792 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002793 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002794 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002795 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002796 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002797 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002798
Radek Krejci1d82ef62015-08-07 14:44:40 +02002799 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002800 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002802
Radek Krejci3cf9e222015-06-18 11:37:50 +02002803 if (c_ftrs) {
2804 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002805 if (!choice->features) {
2806 LOGMEM;
2807 goto error;
2808 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002809 }
2810
Radek Krejci73adb602015-07-02 18:07:40 +02002811 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002812 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002813 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002814 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002815 goto error;
2816 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002817 }
2818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002820 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002821 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2822 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 goto error;
2824 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 /* link default with the case */
2827 if (dflt_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002828 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002829 goto error;
2830 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002834
2835error:
2836
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002837 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002840}
2841
Michal Vasko0d343d12015-08-24 14:57:36 +02002842/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002843static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002844read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002845 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002846{
Radek Krejci76512572015-08-04 09:47:08 +02002847 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002848 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 struct lyxml_elem *sub, *next;
2850 const char *value;
2851 int r;
2852 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002853 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002856 if (!anyxml) {
2857 LOGMEM;
2858 return NULL;
2859 }
Radek Krejci76512572015-08-04 09:47:08 +02002860 anyxml->nodetype = LYS_ANYXML;
2861 anyxml->prev = (struct lys_node *)anyxml;
2862 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002863
Michal Vaskoe0c59842015-09-24 13:52:20 +02002864 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2865 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 goto error;
2867 }
Radek Krejci863c2852015-06-03 15:47:11 +02002868
Radek Krejcia9544502015-08-14 08:24:29 +02002869 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002870
Radek Krejcic4283442016-04-22 09:19:27 +02002871 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002872 goto error;
2873 }
2874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002876 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2877 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002878 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002879 continue;
2880 }
2881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002882 if (!strcmp(sub->name, "mandatory")) {
2883 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002884 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 goto error;
2886 }
2887 /* just checking the flags in leaf is not sufficient, we would allow
2888 * multiple mandatory statements with the "false" value
2889 */
2890 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 GETVAL(value, sub, "value");
2893 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002894 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002895 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002896 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002897 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002898 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 goto error;
2900 }
2901 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002902 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002903 } else if (!strcmp(sub->name, "when")) {
2904 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002905 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002906 goto error;
2907 }
2908
2909 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002910 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002911 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002912 goto error;
2913 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002914 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 } else if (!strcmp(sub->name, "must")) {
2916 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002917 } else if (!strcmp(sub->name, "if-feature")) {
2918 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002921 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 }
2924 }
Radek Krejci863c2852015-06-03 15:47:11 +02002925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 /* middle part - process nodes with cardinality of 0..n */
2927 if (c_must) {
2928 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002929 if (!anyxml->must) {
2930 LOGMEM;
2931 goto error;
2932 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002934 if (c_ftrs) {
2935 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002936 if (!anyxml->features) {
2937 LOGMEM;
2938 goto error;
2939 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002940 }
Radek Krejci863c2852015-06-03 15:47:11 +02002941
Radek Krejci73adb602015-07-02 18:07:40 +02002942 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002944 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2945 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 if (r) {
2947 goto error;
2948 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002949 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002950 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002951 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002952 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002953 goto error;
2954 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 }
Radek Krejci863c2852015-06-03 15:47:11 +02002957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002959
2960error:
2961
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002962 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02002963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002965}
2966
Michal Vasko0d343d12015-08-24 14:57:36 +02002967/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002968static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002969read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002970 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002971{
Radek Krejci76512572015-08-04 09:47:08 +02002972 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002973 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002974 struct lyxml_elem *sub, *next;
2975 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01002976 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002977 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01002980 if (!leaf) {
2981 LOGMEM;
2982 return NULL;
2983 }
Radek Krejci76512572015-08-04 09:47:08 +02002984 leaf->nodetype = LYS_LEAF;
2985 leaf->prev = (struct lys_node *)leaf;
2986 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002987
Michal Vaskoe0c59842015-09-24 13:52:20 +02002988 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2989 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 goto error;
2991 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002992
Radek Krejcia9544502015-08-14 08:24:29 +02002993 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002994
Radek Krejcic4283442016-04-22 09:19:27 +02002995 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002996 goto error;
2997 }
2998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003000 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3001 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003002 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003003 continue;
3004 }
3005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003007 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003008 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 goto error;
3010 }
Michal Vasko88c29542015-11-27 14:57:53 +01003011 /* HACK for unres */
3012 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003013 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci48464ed2016-03-17 15:44:09 +01003014 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003015 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 goto error;
3017 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003018 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 } else if (!strcmp(sub->name, "default")) {
3020 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003021 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 goto error;
3023 }
3024 GETVAL(value, sub, "value");
3025 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3026 } else if (!strcmp(sub->name, "units")) {
3027 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003028 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 goto error;
3030 }
3031 GETVAL(value, sub, "name");
3032 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3033 } else if (!strcmp(sub->name, "mandatory")) {
3034 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003035 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003036 goto error;
3037 }
3038 /* just checking the flags in leaf is not sufficient, we would allow
3039 * multiple mandatory statements with the "false" value
3040 */
3041 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 GETVAL(value, sub, "value");
3044 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003045 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003046 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003047 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003048 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003049 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 goto error;
3051 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003052 } else if (!strcmp(sub->name, "when")) {
3053 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003054 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003055 goto error;
3056 }
3057
3058 leaf->when = read_yin_when(module, sub);
3059 if (!leaf->when) {
3060 goto error;
3061 }
3062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003064 c_must++;
3065 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003066 } else if (!strcmp(sub->name, "if-feature")) {
3067 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003071 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003074
Michal Vasko88c29542015-11-27 14:57:53 +01003075 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003076 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003079 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003080 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 goto error;
3082 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003083 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003084 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003085 goto error;
3086 }
Radek Krejci841ec082016-04-05 13:05:17 +02003087 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003088 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003089 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003090 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003091 goto error;
3092 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 /* middle part - process nodes with cardinality of 0..n */
3096 if (c_must) {
3097 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003098 if (!leaf->must) {
3099 LOGMEM;
3100 goto error;
3101 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003103 if (c_ftrs) {
3104 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003105 if (!leaf->features) {
3106 LOGMEM;
3107 goto error;
3108 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003109 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003110
Radek Krejci73adb602015-07-02 18:07:40 +02003111 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003112 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003113 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3114 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 if (r) {
3116 goto error;
3117 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003118 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003119 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003120 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003121 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003122 goto error;
3123 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003128
3129error:
3130
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003131 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003134}
3135
Michal Vasko0d343d12015-08-24 14:57:36 +02003136/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003137static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003138read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003139 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003140{
Radek Krejci76512572015-08-04 09:47:08 +02003141 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003142 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003143 struct lyxml_elem *sub, *next;
3144 const char *value;
3145 char *endptr;
3146 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003147 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003148 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003151 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003152 if (!llist) {
3153 LOGMEM;
3154 return NULL;
3155 }
Radek Krejci76512572015-08-04 09:47:08 +02003156 llist->nodetype = LYS_LEAFLIST;
3157 llist->prev = (struct lys_node *)llist;
3158 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003159
Michal Vaskoe0c59842015-09-24 13:52:20 +02003160 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3161 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 goto error;
3163 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003164
Radek Krejcia9544502015-08-14 08:24:29 +02003165 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003166
Radek Krejcic4283442016-04-22 09:19:27 +02003167 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003168 goto error;
3169 }
3170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003172 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3173 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003174 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003175 continue;
3176 }
3177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003179 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003180 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 goto error;
3182 }
Michal Vasko88c29542015-11-27 14:57:53 +01003183 /* HACK for unres */
3184 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003185 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci48464ed2016-03-17 15:44:09 +01003186 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003187 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 goto error;
3189 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003190 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 } else if (!strcmp(sub->name, "units")) {
3192 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003193 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 goto error;
3195 }
3196 GETVAL(value, sub, "name");
3197 llist->units = lydict_insert(module->ctx, value, strlen(value));
3198 } else if (!strcmp(sub->name, "ordered-by")) {
3199 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 goto error;
3202 }
3203 /* just checking the flags in llist is not sufficient, we would
3204 * allow multiple ordered-by statements with the "system" value
3205 */
3206 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003207
Radek Krejci1574a8d2015-08-03 14:16:52 +02003208 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003209 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3210 * state data
3211 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003212 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 continue;
3214 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 GETVAL(value, sub, "value");
3217 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003218 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003220 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003222 } /* else system is the default value, so we can ignore it */
3223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 } else if (!strcmp(sub->name, "must")) {
3225 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003226 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003227 } else if (!strcmp(sub->name, "if-feature")) {
3228 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 } else if (!strcmp(sub->name, "min-elements")) {
3232 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003233 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 goto error;
3235 }
3236 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 GETVAL(value, sub, "value");
3239 while (isspace(value[0])) {
3240 value++;
3241 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 /* convert it to uint32_t */
3244 errno = 0;
3245 endptr = NULL;
3246 val = strtoul(value, &endptr, 10);
3247 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003248 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 goto error;
3250 }
3251 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003252 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003253 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3254 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003255 goto error;
3256 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 } else if (!strcmp(sub->name, "max-elements")) {
3258 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003259 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 goto error;
3261 }
3262 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 GETVAL(value, sub, "value");
3265 while (isspace(value[0])) {
3266 value++;
3267 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003268
Radek Krejci0d7b2472016-02-12 11:11:03 +01003269 if (!strcmp(value, "unbounded")) {
3270 llist->max = 0;
3271 } else {
3272 /* convert it to uint32_t */
3273 errno = 0;
3274 endptr = NULL;
3275 val = strtoul(value, &endptr, 10);
3276 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003277 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003278 goto error;
3279 }
3280 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003281 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003282 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3283 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003284 goto error;
3285 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003287 } else if (!strcmp(sub->name, "when")) {
3288 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003289 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003290 goto error;
3291 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003292
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003293 llist->when = read_yin_when(module, sub);
3294 if (!llist->when) {
3295 goto error;
3296 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003298 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003301
Michal Vasko88c29542015-11-27 14:57:53 +01003302 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003306 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003307 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 goto error;
3309 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 /* middle part - process nodes with cardinality of 0..n */
3312 if (c_must) {
3313 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003314 if (!llist->must) {
3315 LOGMEM;
3316 goto error;
3317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003319 if (c_ftrs) {
3320 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003321 if (!llist->features) {
3322 LOGMEM;
3323 goto error;
3324 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003325 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003326
Radek Krejci73adb602015-07-02 18:07:40 +02003327 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003329 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3330 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 if (r) {
3332 goto error;
3333 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003334 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003335 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003336 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003337 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003338 goto error;
3339 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003344
3345error:
3346
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003347 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003350}
3351
Michal Vasko0d343d12015-08-24 14:57:36 +02003352/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003353static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003354read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3355 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003356{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003357 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003358 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003360 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003361 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003363 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 char *auxs;
3365 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 /* init */
3368 memset(&root, 0, sizeof root);
3369 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003372 if (!list) {
3373 LOGMEM;
3374 return NULL;
3375 }
Radek Krejci76512572015-08-04 09:47:08 +02003376 list->nodetype = LYS_LIST;
3377 list->prev = (struct lys_node *)list;
3378 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003379
Michal Vaskoe0c59842015-09-24 13:52:20 +02003380 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3381 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 goto error;
3383 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003384
Radek Krejcia9544502015-08-14 08:24:29 +02003385 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 /* process list's specific children */
3388 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003389 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3390 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003391 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003392 continue;
3393 }
3394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 /* data statements */
3396 if (!strcmp(sub->name, "container") ||
3397 !strcmp(sub->name, "leaf-list") ||
3398 !strcmp(sub->name, "leaf") ||
3399 !strcmp(sub->name, "list") ||
3400 !strcmp(sub->name, "choice") ||
3401 !strcmp(sub->name, "uses") ||
3402 !strcmp(sub->name, "grouping") ||
3403 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003404 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003405 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 /* array counters */
3408 } else if (!strcmp(sub->name, "key")) {
3409 /* check cardinality 0..1 */
3410 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003411 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 goto error;
3413 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 /* count the number of keys */
3416 GETVAL(value, sub, "value");
3417 key_str = value;
3418 while ((value = strpbrk(value, " \t\n"))) {
3419 list->keys_size++;
3420 while (isspace(*value)) {
3421 value++;
3422 }
3423 }
3424 list->keys_size++;
3425 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003426 if (!list->keys) {
3427 LOGMEM;
3428 goto error;
3429 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 } else if (!strcmp(sub->name, "unique")) {
3431 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003432 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003433 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 } else if (!strcmp(sub->name, "typedef")) {
3435 c_tpdf++;
3436 } else if (!strcmp(sub->name, "must")) {
3437 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003438 } else if (!strcmp(sub->name, "if-feature")) {
3439 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 /* optional stetments */
3442 } else if (!strcmp(sub->name, "ordered-by")) {
3443 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003444 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003445 goto error;
3446 }
3447 /* just checking the flags in llist is not sufficient, we would
3448 * allow multiple ordered-by statements with the "system" value
3449 */
3450 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003451
Radek Krejci1574a8d2015-08-03 14:16:52 +02003452 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3454 * state data
3455 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003456 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 continue;
3458 }
Radek Krejci345ad742015-06-03 11:04:18 +02003459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 GETVAL(value, sub, "value");
3461 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003462 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003464 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 goto error;
3466 }
3467 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003468 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 } else if (!strcmp(sub->name, "min-elements")) {
3470 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003471 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 goto error;
3473 }
3474 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 GETVAL(value, sub, "value");
3477 while (isspace(value[0])) {
3478 value++;
3479 }
Radek Krejci345ad742015-06-03 11:04:18 +02003480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 /* convert it to uint32_t */
3482 errno = 0;
3483 auxs = NULL;
3484 val = strtoul(value, &auxs, 10);
3485 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003486 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003487 goto error;
3488 }
3489 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003490 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003491 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3492 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003493 lyxml_free(module->ctx, sub);
3494 goto error;
3495 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003496 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 } else if (!strcmp(sub->name, "max-elements")) {
3498 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003499 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 goto error;
3501 }
3502 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 GETVAL(value, sub, "value");
3505 while (isspace(value[0])) {
3506 value++;
3507 }
Radek Krejci345ad742015-06-03 11:04:18 +02003508
Radek Krejci0d7b2472016-02-12 11:11:03 +01003509 if (!strcmp(value, "unbounded")) {
3510 list->max = 0;;
3511 } else {
3512 /* convert it to uint32_t */
3513 errno = 0;
3514 auxs = NULL;
3515 val = strtoul(value, &auxs, 10);
3516 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003517 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003518 goto error;
3519 }
3520 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003521 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003522 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3523 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003524 goto error;
3525 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003527 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003528 } else if (!strcmp(sub->name, "when")) {
3529 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003530 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003531 goto error;
3532 }
3533
3534 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003535 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003536 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003537 goto error;
3538 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003539 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003540 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003541 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003542 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 }
3544 }
Radek Krejci345ad742015-06-03 11:04:18 +02003545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003547 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003548 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 goto error;
3550 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3553 if (c_tpdf) {
3554 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003555 if (!list->tpdf) {
3556 LOGMEM;
3557 goto error;
3558 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003560 if (c_must) {
3561 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003562 if (!list->must) {
3563 LOGMEM;
3564 goto error;
3565 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003566 }
3567 if (c_ftrs) {
3568 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003569 if (!list->features) {
3570 LOGMEM;
3571 goto error;
3572 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003573 }
Radek Krejci73adb602015-07-02 18:07:40 +02003574 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003576 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3577 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 if (r) {
3579 goto error;
3580 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003581 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003582 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003583 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003584 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003585 goto error;
3586 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003587 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003588 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3589 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003590 if (r) {
3591 goto error;
3592 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 }
3594 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003595
Radek Krejcic4283442016-04-22 09:19:27 +02003596 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003597 goto error;
3598 }
3599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 /* last part - process data nodes */
3601 LY_TREE_FOR_SAFE(root.child, next, sub) {
3602 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003603 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003605 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003607 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003609 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003611 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003613 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003615 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003617 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003618 } else {
3619 LOGINT;
3620 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003622 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 goto error;
3624 }
Radek Krejci73adb602015-07-02 18:07:40 +02003625
Michal Vasko345da0a2015-12-02 10:35:55 +01003626 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003628
Radek Krejci461efb92016-02-12 15:52:18 +01003629 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003630 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003631 goto error;
3632 }
3633 } /* 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 +02003634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 /* process unique statements */
3636 if (c_uniq) {
3637 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003638 if (!list->unique) {
3639 LOGMEM;
3640 goto error;
3641 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003642
Radek Krejci461efb92016-02-12 15:52:18 +01003643 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3644 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3645 list->unique_size++;
3646 if (r) {
3647 goto error;
3648 }
3649
3650 lyxml_free(module->ctx, sub);
3651 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003655
3656error:
3657
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003658 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003660 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003661 }
3662 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003663 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003667}
3668
Michal Vasko0d343d12015-08-24 14:57:36 +02003669/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003670static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003671read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3672 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003673{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003674 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003675 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003676 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003677 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003678 const char *value;
3679 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003680 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 /* init */
3683 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003686 if (!cont) {
3687 LOGMEM;
3688 return NULL;
3689 }
Radek Krejci76512572015-08-04 09:47:08 +02003690 cont->nodetype = LYS_CONTAINER;
3691 cont->prev = (struct lys_node *)cont;
3692 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003693
Michal Vaskoe0c59842015-09-24 13:52:20 +02003694 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3695 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 goto error;
3697 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003698
Radek Krejcia9544502015-08-14 08:24:29 +02003699 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 /* process container's specific children */
3702 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003703 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003704 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003705 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003706 continue;
3707 }
3708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 if (!strcmp(sub->name, "presence")) {
3710 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003711 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 goto error;
3713 }
3714 GETVAL(value, sub, "value");
3715 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003716
Michal Vasko345da0a2015-12-02 10:35:55 +01003717 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003718 } else if (!strcmp(sub->name, "when")) {
3719 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003720 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003721 goto error;
3722 }
3723
3724 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003725 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003726 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003727 goto error;
3728 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003729 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 /* data statements */
3732 } else if (!strcmp(sub->name, "container") ||
3733 !strcmp(sub->name, "leaf-list") ||
3734 !strcmp(sub->name, "leaf") ||
3735 !strcmp(sub->name, "list") ||
3736 !strcmp(sub->name, "choice") ||
3737 !strcmp(sub->name, "uses") ||
3738 !strcmp(sub->name, "grouping") ||
3739 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003740 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003741 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 /* array counters */
3744 } else if (!strcmp(sub->name, "typedef")) {
3745 c_tpdf++;
3746 } else if (!strcmp(sub->name, "must")) {
3747 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003748 } else if (!strcmp(sub->name, "if-feature")) {
3749 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003750 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003751 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 }
3754 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3757 if (c_tpdf) {
3758 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003759 if (!cont->tpdf) {
3760 LOGMEM;
3761 goto error;
3762 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 }
3764 if (c_must) {
3765 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003766 if (!cont->must) {
3767 LOGMEM;
3768 goto error;
3769 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003771 if (c_ftrs) {
3772 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003773 if (!cont->features) {
3774 LOGMEM;
3775 goto error;
3776 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003777 }
Radek Krejci800af702015-06-02 13:46:01 +02003778
Radek Krejci73adb602015-07-02 18:07:40 +02003779 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003781 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3782 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 if (r) {
3784 goto error;
3785 }
3786 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003787 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3788 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 if (r) {
3790 goto error;
3791 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003792 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003793 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003794 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003795 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003796 goto error;
3797 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003800
Radek Krejcic4283442016-04-22 09:19:27 +02003801 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003802 goto error;
3803 }
3804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 /* last part - process data nodes */
3806 LY_TREE_FOR_SAFE(root.child, next, sub) {
3807 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003808 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003810 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003811 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003812 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003814 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003816 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003818 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003820 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003822 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003823 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003824 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003825 goto error;
3826 }
Radek Krejci73adb602015-07-02 18:07:40 +02003827
Michal Vasko345da0a2015-12-02 10:35:55 +01003828 lyxml_free(module->ctx, sub);
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 retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003832
3833error:
3834
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003835 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003837 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003841}
3842
Michal Vasko0d343d12015-08-24 14:57:36 +02003843/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003844static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003845read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003846 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003847{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003849 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003850 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003851 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 int r;
3853 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 /* init */
3856 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003859 if (!grp) {
3860 LOGMEM;
3861 return NULL;
3862 }
Radek Krejci76512572015-08-04 09:47:08 +02003863 grp->nodetype = LYS_GROUPING;
3864 grp->prev = (struct lys_node *)grp;
3865 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003866
Michal Vasko71e1aa82015-08-12 12:17:51 +02003867 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 goto error;
3869 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003870
Radek Krejcia9544502015-08-14 08:24:29 +02003871 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3872
Radek Krejci1d82ef62015-08-07 14:44:40 +02003873 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003874 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3875 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003876 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003877 continue;
3878 }
3879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 /* data statements */
3881 if (!strcmp(sub->name, "container") ||
3882 !strcmp(sub->name, "leaf-list") ||
3883 !strcmp(sub->name, "leaf") ||
3884 !strcmp(sub->name, "list") ||
3885 !strcmp(sub->name, "choice") ||
3886 !strcmp(sub->name, "uses") ||
3887 !strcmp(sub->name, "grouping") ||
3888 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003889 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003890 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 /* array counters */
3893 } else if (!strcmp(sub->name, "typedef")) {
3894 c_tpdf++;
3895 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003896 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 goto error;
3898 }
3899 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3902 if (c_tpdf) {
3903 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003904 if (!grp->tpdf) {
3905 LOGMEM;
3906 goto error;
3907 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003908 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003909 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003910 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3911 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003912 if (r) {
3913 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003916
Radek Krejcic4283442016-04-22 09:19:27 +02003917 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003918 goto error;
3919 }
3920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02003922 if (!root.child) {
3923 LOGWRN("Grouping \"%s\" without children.", retval->name);
3924 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 LY_TREE_FOR_SAFE(root.child, next, sub) {
3926 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003927 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003929 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003931 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003933 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003935 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003937 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003939 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003940 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003943 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 goto error;
3945 }
Radek Krejci73adb602015-07-02 18:07:40 +02003946
Michal Vasko345da0a2015-12-02 10:35:55 +01003947 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003950 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003951
3952error:
3953
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003954 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003956 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960}
3961
Michal Vasko0d343d12015-08-24 14:57:36 +02003962/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003963static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003964read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3965 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003966{
Radek Krejcie0674f82015-06-15 13:58:51 +02003967 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003969 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003970 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003971 int r;
3972 int c_tpdf = 0;
3973
Radek Krejcie0674f82015-06-15 13:58:51 +02003974 /* init */
3975 memset(&root, 0, sizeof root);
3976
Michal Vasko38d01f72015-06-15 09:41:06 +02003977 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01003978 if (!inout) {
3979 LOGMEM;
3980 return NULL;
3981 }
Radek Krejci6acc8012015-08-13 09:07:04 +02003982 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003983
3984 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003985 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02003986 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02003987 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003988 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02003989 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02003990 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003991 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003992 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003993 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003994 }
3995
Radek Krejci76512572015-08-04 09:47:08 +02003996 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003997
Radek Krejci6a113852015-07-03 16:04:20 +02003998 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003999 goto error;
4000 }
4001
Radek Krejcia9544502015-08-14 08:24:29 +02004002 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4003
Michal Vasko38d01f72015-06-15 09:41:06 +02004004 /* data statements */
4005 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004006 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4007 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004008 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004009 continue;
4010 }
4011
Michal Vasko38d01f72015-06-15 09:41:06 +02004012 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004013 !strcmp(sub->name, "leaf-list") ||
4014 !strcmp(sub->name, "leaf") ||
4015 !strcmp(sub->name, "list") ||
4016 !strcmp(sub->name, "choice") ||
4017 !strcmp(sub->name, "uses") ||
4018 !strcmp(sub->name, "grouping") ||
4019 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004020 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004021 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004024 } else if (!strcmp(sub->name, "typedef")) {
4025 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004026
Michal Vasko38d01f72015-06-15 09:41:06 +02004027 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004028 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004029 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004030 }
4031 }
4032
4033 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4034 if (c_tpdf) {
4035 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004036 if (!inout->tpdf) {
4037 LOGMEM;
4038 goto error;
4039 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004040 }
4041
Radek Krejci73adb602015-07-02 18:07:40 +02004042 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004043 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4044 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004045 if (r) {
4046 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004047 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004048 }
4049
Radek Krejcic4283442016-04-22 09:19:27 +02004050 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004051 goto error;
4052 }
4053
Michal Vasko38d01f72015-06-15 09:41:06 +02004054 /* last part - process data nodes */
4055 LY_TREE_FOR_SAFE(root.child, next, sub) {
4056 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004057 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004058 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004059 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004060 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004061 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004062 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004063 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004064 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004065 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004066 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004067 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004068 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004069 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004070 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004071 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004072 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004073 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004074 goto error;
4075 }
Radek Krejci73adb602015-07-02 18:07:40 +02004076
Michal Vasko345da0a2015-12-02 10:35:55 +01004077 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004078 }
4079
Michal Vasko38d01f72015-06-15 09:41:06 +02004080 return retval;
4081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004082error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004083
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004084 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004085 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004086 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004087 }
4088
4089 return NULL;
4090}
4091
Michal Vasko0d343d12015-08-24 14:57:36 +02004092/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004093static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004094read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4095 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004096{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004097 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004098 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004099 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004100 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004101 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004102 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004103
Michal Vaskoc6551b32015-06-16 10:51:43 +02004104 memset(&root, 0, sizeof root);
4105
Michal Vasko0ea41032015-06-16 08:53:55 +02004106 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004107 if (!notif) {
4108 LOGMEM;
4109 return NULL;
4110 }
Radek Krejci76512572015-08-04 09:47:08 +02004111 notif->nodetype = LYS_NOTIF;
4112 notif->prev = (struct lys_node *)notif;
4113 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004114
Radek Krejci6a113852015-07-03 16:04:20 +02004115 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004116 goto error;
4117 }
4118
Radek Krejcia9544502015-08-14 08:24:29 +02004119 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4120
Michal Vasko0ea41032015-06-16 08:53:55 +02004121 /* process rpc's specific children */
4122 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004123 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4124 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004125 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004126 continue;
4127 }
4128
Michal Vasko0ea41032015-06-16 08:53:55 +02004129 /* data statements */
4130 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 !strcmp(sub->name, "leaf-list") ||
4132 !strcmp(sub->name, "leaf") ||
4133 !strcmp(sub->name, "list") ||
4134 !strcmp(sub->name, "choice") ||
4135 !strcmp(sub->name, "uses") ||
4136 !strcmp(sub->name, "grouping") ||
4137 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004138 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004139 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004141 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004142 } else if (!strcmp(sub->name, "typedef")) {
4143 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004144 } else if (!strcmp(sub->name, "if-feature")) {
4145 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004146 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004147 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004148 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004149 }
4150 }
4151
4152 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4153 if (c_tpdf) {
4154 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004155 if (!notif->tpdf) {
4156 LOGMEM;
4157 goto error;
4158 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004159 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004160 if (c_ftrs) {
4161 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004162 if (!notif->features) {
4163 LOGMEM;
4164 goto error;
4165 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004166 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004167
Radek Krejci73adb602015-07-02 18:07:40 +02004168 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004169 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004170 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4171 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004172 if (r) {
4173 goto error;
4174 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004175 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004176 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004177 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004178 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004179 goto error;
4180 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004181 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004182 }
4183
Radek Krejcic4283442016-04-22 09:19:27 +02004184 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004185 goto error;
4186 }
4187
Michal Vasko0ea41032015-06-16 08:53:55 +02004188 /* last part - process data nodes */
4189 LY_TREE_FOR_SAFE(root.child, next, sub) {
4190 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004191 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004192 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004193 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004194 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004195 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004196 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004197 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004198 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004199 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004200 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004201 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004202 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004203 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004204 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004205 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004206 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004207 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004208 goto error;
4209 }
Radek Krejci73adb602015-07-02 18:07:40 +02004210
Michal Vasko345da0a2015-12-02 10:35:55 +01004211 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004212 }
4213
Michal Vasko0ea41032015-06-16 08:53:55 +02004214 return retval;
4215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004216error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004217
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004218 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004219 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004220 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004221 }
4222
4223 return NULL;
4224}
4225
Michal Vasko0d343d12015-08-24 14:57:36 +02004226/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004227static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004228read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4229 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004230{
Radek Krejcie0674f82015-06-15 13:58:51 +02004231 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004232 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004233 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004234 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004235 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004236 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004237
Radek Krejcie0674f82015-06-15 13:58:51 +02004238 /* init */
4239 memset(&root, 0, sizeof root);
4240
Michal Vasko38d01f72015-06-15 09:41:06 +02004241 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004242 if (!rpc) {
4243 LOGMEM;
4244 return NULL;
4245 }
Radek Krejci76512572015-08-04 09:47:08 +02004246 rpc->nodetype = LYS_RPC;
4247 rpc->prev = (struct lys_node *)rpc;
4248 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004249
Radek Krejci6a113852015-07-03 16:04:20 +02004250 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004251 goto error;
4252 }
4253
Radek Krejcia9544502015-08-14 08:24:29 +02004254 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4255
Michal Vasko38d01f72015-06-15 09:41:06 +02004256 /* process rpc's specific children */
4257 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004258 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4259 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004260 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004261 continue;
4262 }
4263
Michal Vasko38d01f72015-06-15 09:41:06 +02004264 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004265 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004266 && (rpc->child->nodetype == LYS_INPUT
4267 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004268 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004269 goto error;
4270 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004271 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004272 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004273 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004274 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004275 && (rpc->child->nodetype == LYS_INPUT
4276 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004277 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004278 goto error;
4279 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004280 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004281 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004284 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004285 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004286 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004288 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004289 } else if (!strcmp(sub->name, "typedef")) {
4290 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004291 } else if (!strcmp(sub->name, "if-feature")) {
4292 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004293 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004294 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004295 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004296 }
4297 }
4298
4299 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4300 if (c_tpdf) {
4301 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004302 if (!rpc->tpdf) {
4303 LOGMEM;
4304 goto error;
4305 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004306 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004307 if (c_ftrs) {
4308 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004309 if (!rpc->features) {
4310 LOGMEM;
4311 goto error;
4312 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004313 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004314
Radek Krejci73adb602015-07-02 18:07:40 +02004315 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004316 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004317 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4318 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004319 if (r) {
4320 goto error;
4321 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004322 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004323 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004324 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004325 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004326 goto error;
4327 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004328 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004329 }
4330
Radek Krejcic4283442016-04-22 09:19:27 +02004331 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004332 goto error;
4333 }
4334
Michal Vasko38d01f72015-06-15 09:41:06 +02004335 /* last part - process data nodes */
4336 LY_TREE_FOR_SAFE(root.child, next, sub) {
4337 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004338 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004339 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004340 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004341 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004342 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004343 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004344 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004345 goto error;
4346 }
Radek Krejci73adb602015-07-02 18:07:40 +02004347
Michal Vasko345da0a2015-12-02 10:35:55 +01004348 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004349 }
4350
Michal Vasko38d01f72015-06-15 09:41:06 +02004351 return retval;
4352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004353error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004354
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004355 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004356 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004357 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004358 }
4359
4360 return NULL;
4361}
4362
Michal Vasko0d343d12015-08-24 14:57:36 +02004363/* logs directly
4364 *
Radek Krejci74705112015-06-05 10:25:44 +02004365 * resolve - referenced grouping should be bounded to the namespace (resolved)
4366 * only when uses does not appear in grouping. In a case of grouping's uses,
4367 * we just get information but we do not apply augment or refine to it.
4368 */
Radek Krejci76512572015-08-04 09:47:08 +02004369static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004370read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004371 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004372{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004374 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004375 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004377 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004381 if (!uses) {
4382 LOGMEM;
4383 return NULL;
4384 }
Radek Krejci76512572015-08-04 09:47:08 +02004385 uses->nodetype = LYS_USES;
4386 uses->prev = (struct lys_node *)uses;
4387 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004388
Radek Krejcia9544502015-08-14 08:24:29 +02004389 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004391
Michal Vaskoe0c59842015-09-24 13:52:20 +02004392 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4393 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004394 goto error;
4395 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004396
Radek Krejcia9544502015-08-14 08:24:29 +02004397 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004400 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004401 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4402 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004403 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004404 continue;
4405 }
4406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 if (!strcmp(sub->name, "refine")) {
4408 c_ref++;
4409 } else if (!strcmp(sub->name, "augment")) {
4410 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004411 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004412 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004413 } else if (!strcmp(sub->name, "when")) {
4414 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004415 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004416 goto error;
4417 }
4418
4419 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004420 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004421 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004422 goto error;
4423 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004424 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004425 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004426 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004428 }
4429 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004431 /* process properties with cardinality 0..n */
4432 if (c_ref) {
4433 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004434 if (!uses->refine) {
4435 LOGMEM;
4436 goto error;
4437 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 }
4439 if (c_aug) {
4440 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004441 if (!uses->augment) {
4442 LOGMEM;
4443 goto error;
4444 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004446 if (c_ftrs) {
4447 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004448 if (!uses->features) {
4449 LOGMEM;
4450 goto error;
4451 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004452 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004453
Radek Krejcic4283442016-04-22 09:19:27 +02004454 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004455 goto error;
4456 }
4457
Radek Krejcia9544502015-08-14 08:24:29 +02004458 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004460 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4461 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004462 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004463 goto error;
4464 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004465 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004466 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4467 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004468 if (r) {
4469 goto error;
4470 }
4471 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004472 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004473 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004474 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004475 goto error;
4476 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004477 }
4478 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004479
Radek Krejci48464ed2016-03-17 15:44:09 +01004480 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004481 goto error;
4482 }
Radek Krejci74705112015-06-05 10:25:44 +02004483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 if (resolve) {
4485 /* inherit config flag */
4486 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004487 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 } else {
4489 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004490 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004491 }
4492 }
Radek Krejcib388c152015-06-04 17:03:03 +02004493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004495
4496error:
4497
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004498 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004501}
4502
Michal Vasko0d343d12015-08-24 14:57:36 +02004503/* logs directly
4504 *
4505 * common code for yin_read_module() and yin_read_submodule()
4506 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507static int
Radek Krejcic071c542016-01-27 14:57:51 +01004508read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4509 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004510{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004512 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004513 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004514 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004515 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004517 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01004518 int inc_size_aux = 0;
4519 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004520 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004521 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 +02004522
Radek Krejcic071c542016-01-27 14:57:51 +01004523 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004524 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 /* init */
4527 memset(&root, 0, sizeof root);
4528 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004529 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 /*
4532 * in the first run, we process elements with cardinality of 1 or 0..1 and
4533 * count elements with cardinality 0..n. Data elements (choices, containers,
4534 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4535 * need have all top-level and groupings already prepared at that time. In
4536 * the middle loop, we process other elements with carinality of 0..n since
4537 * we need to allocate arrays to store them.
4538 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004539 LY_TREE_FOR_SAFE(yin->child, next, child) {
4540 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004541 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004542 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 continue;
4544 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004545
Radek Krejcic071c542016-01-27 14:57:51 +01004546 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004547 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004548 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 goto error;
4550 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004551 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004552 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004553 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004554 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004556 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004557 goto error;
4558 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004559 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004560 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 goto error;
4562 }
4563 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004564 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004565 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4566 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004567 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 goto error;
4569 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004570 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004571 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004572 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 goto error;
4574 }
Radek Krejcif3886932015-06-04 17:36:06 +02004575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004577 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004578 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004580 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004581 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004583 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004584 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 goto error;
4586 }
4587 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004588 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 /* check here differs from a generic prefix check, since this prefix
4590 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004591 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004592 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004593 goto error;
4594 }
Radek Krejcic071c542016-01-27 14:57:51 +01004595 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004598 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004599
4600 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004601 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004603 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004604 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004605 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004608 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004609 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004611 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004612 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004613 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004614 lyxml_unlink_elem(ctx, child, 2);
4615 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004616
Radek Krejci1d82ef62015-08-07 14:44:40 +02004617 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004618 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004620 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004623 } else if (!strcmp(child->name, "container") ||
4624 !strcmp(child->name, "leaf-list") ||
4625 !strcmp(child->name, "leaf") ||
4626 !strcmp(child->name, "list") ||
4627 !strcmp(child->name, "choice") ||
4628 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004629 !strcmp(child->name, "anyxml") ||
4630 !strcmp(child->name, "rpc") ||
4631 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004632 lyxml_unlink_elem(ctx, child, 2);
4633 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004634
Radek Krejci1d82ef62015-08-07 14:44:40 +02004635 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004637 lyxml_unlink_elem(ctx, child, 2);
4638 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004641 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004642 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004643 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 goto error;
4645 }
Radek Krejcic071c542016-01-27 14:57:51 +01004646 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004647 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004648 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 goto error;
4650 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004652 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004653 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 goto error;
4655 }
Radek Krejcic071c542016-01-27 14:57:51 +01004656 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004657 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004658 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 goto error;
4660 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004661 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004662 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004663 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664 goto error;
4665 }
Radek Krejcic071c542016-01-27 14:57:51 +01004666 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004667 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004668 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 goto error;
4670 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004672 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004673 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 goto error;
4675 }
Radek Krejcic071c542016-01-27 14:57:51 +01004676 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004677 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004678 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 goto error;
4680 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004681 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004683 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004684 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 goto error;
4686 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004687 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 if (strcmp(value, "1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004689 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 goto error;
4691 }
Radek Krejcic071c542016-01-27 14:57:51 +01004692 version_flag = 1;
4693 if (!submodule) {
4694 module->version = 1;
4695 } /* 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 +01004696 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004697
Radek Krejci1d82ef62015-08-07 14:44:40 +02004698 } else if (!strcmp(child->name, "extension")) {
4699 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004700
Radek Krejci3d468122015-10-02 13:36:12 +02004701 /* we have the following supported (hardcoded) extensions: */
4702 /* ietf-netconf's get-filter-element-attributes */
4703 if (!strcmp(module->ns, LY_NSNC) &&
4704 !strcmp(value, "get-filter-element-attributes")) {
4705 LOGDBG("NETCONF filter extension found");
4706 /* NACM's default-deny-write and default-deny-all */
4707 } else if (!strcmp(module->ns, LY_NSNACM) &&
4708 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4709 LOGDBG("NACM extension found");
4710 /* other extensions are not supported, so inform about such an extension */
4711 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004712 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004713 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004714 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004715 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004716 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004717 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 }
4719 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004720
Radek Krejcic071c542016-01-27 14:57:51 +01004721 /* check for mandatory statements */
4722 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004723 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004724 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004725 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004727 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 goto error;
4729 }
4730 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004731 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 goto error;
4733 }
4734 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 /* allocate arrays for elements with cardinality of 0..n */
4737 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004738 trg->imp = calloc(c_imp, sizeof *trg->imp);
4739 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004740 LOGMEM;
4741 goto error;
4742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004743 }
4744 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004745 trg->rev = calloc(c_rev, sizeof *trg->rev);
4746 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004747 LOGMEM;
4748 goto error;
4749 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 }
4751 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004752 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4753 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004754 LOGMEM;
4755 goto error;
4756 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 }
4758 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004759 trg->ident = calloc(c_ident, sizeof *trg->ident);
4760 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004761 LOGMEM;
4762 goto error;
4763 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 }
4765 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004766 trg->inc = calloc(c_inc, sizeof *trg->inc);
4767 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004768 LOGMEM;
4769 goto error;
4770 }
Radek Krejcic071c542016-01-27 14:57:51 +01004771 trg->inc_size = c_inc;
4772 /* trg->inc_size can be updated by the included submodules,
4773 * so we will use inc_size_aux here, trg->inc_size stores the
4774 * target size of the array
4775 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004777 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004778 trg->augment = calloc(c_aug, sizeof *trg->augment);
4779 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004780 LOGMEM;
4781 goto error;
4782 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004783 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004784 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004785 trg->features = calloc(c_ftrs, sizeof *trg->features);
4786 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004787 LOGMEM;
4788 goto error;
4789 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004790 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004791 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004792 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4793 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004794 LOGMEM;
4795 goto error;
4796 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004797 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004798
Michal Vasko2f7925f2015-10-21 15:06:56 +02004799 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4800 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004801 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004802 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4803 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 if (r) {
4805 goto error;
4806 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004808 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004809 for (i = 0; i < trg->imp_size - 1; i++) {
4810 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004811 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->imp[i].module->name, "import");
4812 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 goto error;
4814 }
4815 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004816
Radek Krejci1d82ef62015-08-07 14:44:40 +02004817 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004818 memset(&inc, 0, sizeof inc);
4819 /* 1) pass module, not trg, since we want to pass the main module
4820 * 2) we cannot pass directly the structure in the array since
4821 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004822 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004823 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4824 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004825 if (r) {
4826 goto error;
4827 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004829 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004830 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004831 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 +01004832 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
4833 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01004834 trg->inc[inc_size_aux - 1].submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 goto error;
4836 }
4837 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004838
Radek Krejci1d82ef62015-08-07 14:44:40 +02004839 } else if (!strcmp(child->name, "revision")) {
4840 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004841 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 goto error;
4843 }
Radek Krejcic071c542016-01-27 14:57:51 +01004844 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004846 for (i = 0; i < trg->rev_size; i++) {
4847 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004848 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4849 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004850 }
4851 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004852
Radek Krejci1d82ef62015-08-07 14:44:40 +02004853 LY_TREE_FOR(child->child, child2) {
4854 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004855 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004856 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 goto error;
4858 }
Radek Krejcic071c542016-01-27 14:57:51 +01004859 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4860 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 goto error;
4862 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004863 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004864 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004865 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 goto error;
4867 }
Radek Krejcic071c542016-01-27 14:57:51 +01004868 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4869 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 goto error;
4871 }
4872 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004873 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 goto error;
4875 }
4876 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004879 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004880 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004881 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004882 if (!value) {
4883 LOGMEM;
4884 goto error;
4885 }
Radek Krejcic071c542016-01-27 14:57:51 +01004886 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4887 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004889
Radek Krejci749190d2016-02-18 16:26:25 +01004890 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004891 value = trg->rev[0].dsc;
4892 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4893 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004895
Radek Krejci749190d2016-02-18 16:26:25 +01004896 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004897 value = trg->rev[0].ref;
4898 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4899 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004900 }
4901 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004902
Radek Krejcic071c542016-01-27 14:57:51 +01004903 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004904
Radek Krejci1d82ef62015-08-07 14:44:40 +02004905 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004906 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4907 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 if (r) {
4909 goto error;
4910 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004911
Radek Krejci1d82ef62015-08-07 14:44:40 +02004912 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004913 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4914 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 if (r) {
4916 goto error;
4917 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004918
Radek Krejci1d82ef62015-08-07 14:44:40 +02004919 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004920 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4921 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004922 if (r) {
4923 goto error;
4924 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004925
Radek Krejci1d82ef62015-08-07 14:44:40 +02004926 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004927 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4928 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004929 if (r) {
4930 goto error;
4931 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004932 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4933 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004934
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004937
Pavol Vicane994fda2016-03-22 10:47:58 +01004938 if (submodule && lyp_propagate_submodule(module, submodule)) {
Pavol Vicanaa1eba92016-03-09 12:27:11 +01004939 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004940 }
4941
Radek Krejcif5be10f2015-06-16 13:29:36 +02004942 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004943 * refer to them. Submodule's data nodes are stored in the
4944 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004946 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004947 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004948 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004949 goto error;
4950 }
Radek Krejci74705112015-06-05 10:25:44 +02004951
Michal Vasko345da0a2015-12-02 10:35:55 +01004952 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 }
Radek Krejci74705112015-06-05 10:25:44 +02004954
Radek Krejcif5be10f2015-06-16 13:29:36 +02004955 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004956 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004957
Radek Krejci1d82ef62015-08-07 14:44:40 +02004958 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004959 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004960 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004961 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004962 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004963 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004964 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004965 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004966 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004967 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004968 } else if (!strcmp(child->name, "uses")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004969 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004970 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004971 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004972 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004973 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004974 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004975 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004977 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004978 goto error;
4979 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004980
Michal Vasko345da0a2015-12-02 10:35:55 +01004981 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004983
Michal Vasko2f7925f2015-10-21 15:06:56 +02004984 /* ... and finally augments (last, so we can augment our data, for instance) */
4985 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004986 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
4987 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004988
Michal Vasko2f7925f2015-10-21 15:06:56 +02004989 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004990 goto error;
4991 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004992 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004993 }
4994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004995 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004996
4997error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004998 /* cleanup */
4999 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005000 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 }
5002 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005003 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005005 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005006 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005007 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005009 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005010}
5011
Michal Vasko0d343d12015-08-24 14:57:36 +02005012/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005013struct lys_submodule *
5014yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005015{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005017 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005019
Michal Vasko5a721fd2016-02-16 12:16:48 +01005020 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005021
Radek Krejci722b0072016-02-01 17:09:45 +01005022 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005024 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005025 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 /* check root element */
5028 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005029 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005030 goto error;
5031 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005033 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005034 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 goto error;
5036 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005037
Michal Vasko5a721fd2016-02-16 12:16:48 +01005038 submodule = calloc(1, sizeof *submodule);
5039 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005040 LOGMEM;
5041 goto error;
5042 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005043
Michal Vasko5a721fd2016-02-16 12:16:48 +01005044 submodule->ctx = module->ctx;
5045 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5046 submodule->type = 1;
5047 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005048
Michal Vasko5a721fd2016-02-16 12:16:48 +01005049 LOGVRB("Reading submodule \"%s\".", submodule->name);
5050 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005051 goto error;
5052 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005054 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005055 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005056
Michal Vasko5a721fd2016-02-16 12:16:48 +01005057 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005058 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005059
5060error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005061 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005062 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005063 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005064
Michal Vasko5a721fd2016-02-16 12:16:48 +01005065 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005066 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005067 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005068 }
5069
Michal Vasko5a721fd2016-02-16 12:16:48 +01005070 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005071
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005072 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5073 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005074 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005075 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005076}
5077
Michal Vasko0d343d12015-08-24 14:57:36 +02005078/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005079struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005080yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005081{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005082 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005083 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005084 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005086 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005087
Radek Krejcic071c542016-01-27 14:57:51 +01005088 unres = calloc(1, sizeof *unres);
5089 if (!unres) {
5090 LOGMEM;
5091 return NULL;
5092 }
5093
Radek Krejci722b0072016-02-01 17:09:45 +01005094 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005095 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005096 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005097 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005099 /* check root element */
5100 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005101 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005102 goto error;
5103 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005105 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005106 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005107 goto error;
5108 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005110 module = calloc(1, sizeof *module);
5111 if (!module) {
5112 LOGMEM;
5113 goto error;
5114 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 module->ctx = ctx;
5117 module->name = lydict_insert(ctx, value, strlen(value));
5118 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005119 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005120
Michal Vasko9f258e42016-02-11 11:36:27 +01005121 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005122 if (read_sub_module(module, NULL, yin, unres)) {
5123 goto error;
5124 }
5125
5126 /* resolve rest of unres items */
5127 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005128 goto error;
5129 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005130
Radek Krejciff4874d2016-03-07 12:30:50 +01005131 if (revision) {
5132 /* check revision of the parsed model */
5133 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005134 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5135 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005136 goto error;
5137 }
5138 }
5139
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005140 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005141 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005142 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005143
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005144 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005145 if (!module->implemented) {
5146 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5147 }
Michal Vasko26055752016-05-03 11:36:31 +02005148 if (lys_module_set_implement(module)) {
5149 goto error;
5150 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005151
Michal Vasko26055752016-05-03 11:36:31 +02005152 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5153 goto error;
5154 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005155 for (i = 0; i < module->inc_size; ++i) {
Michal Vasko26055752016-05-03 11:36:31 +02005156 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5157 goto error;
5158 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005159 }
5160 }
5161
Michal Vasko345da0a2015-12-02 10:35:55 +01005162 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005163 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005164 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005165 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005166
5167error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005168 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005169 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005170 unres_schema_free(module, &unres);
5171
5172 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005173 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005174 return NULL;
5175 }
5176
5177 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005178
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005179 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005180 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005182}