blob: be893abd5e0db380618bc4be6afb7c01568a6c13 [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Radek Krejci812b10a2015-05-28 16:48:25 +020022#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020023#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020024#include <errno.h>
25#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020026#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020027#include <stdlib.h>
28#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020029#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020030#include <sys/types.h>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020031#include <pcre.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020032
Radek Krejci998a0b82015-08-17 13:14:36 +020033#include "libyang.h"
34#include "common.h"
35#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020036#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020037#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020038#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020039#include "resolve.h"
40#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020041#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020042
Radek Krejciadb57612016-02-16 13:34:34 +010043#define GETVAL(value, node, arg) \
44 value = lyxml_get_attr(node, arg, NULL); \
45 if (!value) { \
46 LOGVAL(LYE_MISSARG, LOGLINE(node), LY_VLOG_XML, node, arg, node->name); \
47 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010048 }
Radek Krejcice7fb782015-05-29 16:52:34 +020049
Radek Krejcic6556022016-01-27 15:16:45 +010050/* parser.c */
51int dup_prefix_check(const char *prefix, struct lys_module *module);
52
Radek Krejcib388c152015-06-04 17:03:03 +020053#define OPT_IDENT 0x01
54#define OPT_CONFIG 0x02
55#define OPT_MODULE 0x04
56#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020057#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020058static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020059
Radek Krejcib8048692015-08-05 13:36:34 +020060static 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 +020061 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static 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 +020063 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020064static 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 +020065 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020066static 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 +020067 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020068static 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 +020069 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020070static 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 +020071 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020072static 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 +020073 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020074static 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 +020075 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020076static 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 +020077 int resolve, struct unres_schema *unres);
78static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020079
Michal Vasko0d343d12015-08-24 14:57:36 +020080/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020081static const char *
82read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020083{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020086 /* there should be <text> child */
87 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010088 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejciadb57612016-02-16 13:34:34 +010089 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010090 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020091 } else if (node->child->content) {
92 len = strlen(node->child->content);
93 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010094 } else {
95 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020096 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020097}
98
Michal Vasko0d343d12015-08-24 14:57:36 +020099/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200100static int
Michal Vasko1d337e12016-02-15 12:32:04 +0100101fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
102{
103 int r;
104 const char *value;
105
106 GETVAL(value, yin, "name");
107 if (!(value = transform_schema2json(parent->module, value, LOGLINE(yin)))) {
108 return EXIT_FAILURE;
109 }
110
111 /* HACK - store pointer to the parent node for later status check */
112 *iffeat = (struct lys_feature *)parent;
113 r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value,
114 LOGLINE(yin));
115 lydict_remove(parent->module->ctx, value);
116 if (!r) {
117 return EXIT_SUCCESS;
118 }
119
120error:
121 return EXIT_FAILURE;
122}
123
124/* logs directly */
125static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200126fill_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 +0200127{
Radek Krejci73adb602015-07-02 18:07:40 +0200128 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200129 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100130 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200131
Michal Vasko4cfcd252015-08-03 14:31:10 +0200132 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100133 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200134
Radek Krejci76512572015-08-04 09:47:08 +0200135 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200136 return EXIT_FAILURE;
137 }
Radek Krejci04581c62015-05-22 21:24:00 +0200138
Radek Krejci73adb602015-07-02 18:07:40 +0200139 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200140 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
141 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200142 continue;
143 }
144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200145 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100146 if (base_flag) {
Radek Krejciadb57612016-02-16 13:34:34 +0100147 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200148 return EXIT_FAILURE;
149 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100150 base_flag = 1;
151
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200152 GETVAL(value, node, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100153 value = transform_schema2json(module, value, LOGLINE(node));
154 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200155 return EXIT_FAILURE;
156 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100157
158 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
159 lydict_remove(module->ctx, value);
160 return EXIT_FAILURE;
161 }
162 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200163 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100164 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200165 return EXIT_FAILURE;
166 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200167 }
Radek Krejci04581c62015-05-22 21:24:00 +0200168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200169 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200170
171error:
172 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200173}
174
Michal Vasko0d343d12015-08-24 14:57:36 +0200175/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200176static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200177read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200178{
Radek Krejci73adb602015-07-02 18:07:40 +0200179 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200180 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200181
Radek Krejci73adb602015-07-02 18:07:40 +0200182 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200183 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
184 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200185 continue;
186 }
187
Radek Krejci41726f92015-06-19 13:11:05 +0200188 if (!strcmp(child->name, "description")) {
189 if (restr->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +0100190 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200191 return EXIT_FAILURE;
192 }
193 restr->dsc = read_yin_subnode(ctx, child, "text");
194 if (!restr->dsc) {
195 return EXIT_FAILURE;
196 }
197 } else if (!strcmp(child->name, "reference")) {
198 if (restr->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +0100199 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200200 return EXIT_FAILURE;
201 }
202 restr->ref = read_yin_subnode(ctx, child, "text");
203 if (!restr->ref) {
204 return EXIT_FAILURE;
205 }
206 } else if (!strcmp(child->name, "error-app-tag")) {
207 if (restr->eapptag) {
Radek Krejciadb57612016-02-16 13:34:34 +0100208 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200209 return EXIT_FAILURE;
210 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200211 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200212 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200213 } else if (!strcmp(child->name, "error-message")) {
214 if (restr->emsg) {
Radek Krejciadb57612016-02-16 13:34:34 +0100215 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200216 return EXIT_FAILURE;
217 }
218 restr->emsg = read_yin_subnode(ctx, child, "value");
219 if (!restr->emsg) {
220 return EXIT_FAILURE;
221 }
222 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100223 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200224 return EXIT_FAILURE;
225 }
Radek Krejci41726f92015-06-19 13:11:05 +0200226 }
227
228 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200229
230error:
231 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200232}
233
Michal Vasko88c29542015-11-27 14:57:53 +0100234/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
235int
Radek Krejcib8048692015-08-05 13:36:34 +0200236fill_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 +0200237 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200238{
Michal Vasko1dca6882015-10-22 14:29:42 +0200239 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200240 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200241 struct lys_restr **restr;
242 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200243 pcre *precomp;
244 int i, j, rc, err_offset;
Radek Krejcidc008d72016-02-17 13:12:14 +0100245 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200246 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200247 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200248
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200249 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200250 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200251 if (!value) {
252 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200253 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200254
255 i = parse_identifier(value);
256 if (i < 1) {
Radek Krejciadb57612016-02-16 13:34:34 +0100257 LOGVAL(LYE_INCHAR, LOGLINE(yin), LY_VLOG_XML, yin, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100258 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200259 goto error;
260 }
261 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100262 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200263 if (value[i]) {
264 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100265 name += i;
266 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
267 LOGVAL(LYE_INCHAR, LOGLINE(yin), LY_VLOG_XML, yin, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100268 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200269 goto error;
270 }
Radek Krejci225376f2016-02-16 17:36:22 +0100271 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200272 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200273
Radek Krejci225376f2016-02-16 17:36:22 +0100274 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100275 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200276 if (rc == -1) {
Radek Krejciadb57612016-02-16 13:34:34 +0100277 LOGVAL(LYE_INMOD, LOGLINE(yin), LY_VLOG_XML, yin, type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200278 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100279
280 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200281 } else if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100282 ret = EXIT_FAILURE;
283 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200284 }
285 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200286
Radek Krejcicf509982015-12-15 09:22:44 +0100287 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100288 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejciadb57612016-02-16 13:34:34 +0100289 type->der->flags, type->der->module, type->der->name, LOGLINE(yin), parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100290 return -1;
291 }
292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200293 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200294 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200295 /* RFC 6020 9.7.4 - bit */
296
297 /* get bit specifications, at least one must be present */
298 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200299 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
300 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100301 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200302 continue;
303 }
304
Radek Krejci994b6f62015-06-18 16:47:27 +0200305 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200306 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200307 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100308 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200309 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200310 }
311 }
Radek Krejciac781922015-07-09 15:35:14 +0200312 if (!type->der->type.der && !type->info.bits.count) {
313 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejciadb57612016-02-16 13:34:34 +0100314 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200315 goto error;
316 }
Radek Krejciac781922015-07-09 15:35:14 +0200317 if (type->der->type.der && type->info.bits.count) {
318 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejciadb57612016-02-16 13:34:34 +0100319 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200320 goto error;
321 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200322
323 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100324 if (!type->info.bits.bit) {
325 LOGMEM;
326 goto error;
327 }
Radek Krejci73adb602015-07-02 18:07:40 +0200328 p = 0;
329 i = -1;
330 LY_TREE_FOR(yin->child, next) {
331 i++;
332
333 GETVAL(value, next, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100334 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100335 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, next);
Michal Vasko2d26a022015-12-07 09:27:21 +0100336 goto error;
337 }
338
Radek Krejci994b6f62015-06-18 16:47:27 +0200339 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200340 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200341 type->info.bits.count = i + 1;
342 goto error;
343 }
344
345 /* check the name uniqueness */
346 for (j = 0; j < i; j++) {
347 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100348 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), LY_VLOG_XML, next, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200349 type->info.bits.count = i + 1;
350 goto error;
351 }
352 }
353
Radek Krejci0d70c372015-07-02 16:23:10 +0200354 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200355 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200356 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
357 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200358 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200359 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200360
Radek Krejci0d70c372015-07-02 16:23:10 +0200361 if (!strcmp(node->name, "position")) {
362 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200363 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200364
365 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200366 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100367 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200368 type->info.bits.count = i + 1;
369 goto error;
370 }
371 type->info.bits.bit[i].pos = (uint32_t)p_;
372
373 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200374 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200375 p = type->info.bits.bit[i].pos;
376 p++;
377 } else {
378 /* check that the value is unique */
379 for (j = 0; j < i; j++) {
380 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejciadb57612016-02-16 13:34:34 +0100381 LOGVAL(LYE_BITS_DUPVAL, LOGLINE(node), LY_VLOG_XML, node,
382 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200383 type->info.bits.count = i + 1;
384 goto error;
385 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200386 }
387 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200388 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100389 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200390 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200391 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200392 }
393 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200394 /* assign value automatically */
395 if (p > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100396 LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_XML, next, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200397 type->info.bits.count = i + 1;
398 goto error;
399 }
400 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100401 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200402 p++;
403 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200404
405 /* keep them ordered by position */
406 j = i;
407 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
408 /* switch them */
409 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
410 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
411 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
412 j--;
413 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200414 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200415 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200417 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200418 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200419 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200420 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
421 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200422 continue;
423 }
424
Radek Krejcif9401c32015-06-26 16:47:36 +0200425 if (!strcmp(node->name, "range")) {
426 if (type->info.dec64.range) {
Radek Krejciadb57612016-02-16 13:34:34 +0100427 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200428 goto error;
429 }
430
431 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200432 if (lyp_check_length_range(value, type)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100433 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200434 goto error;
435 }
436 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100437 if (!type->info.dec64.range) {
438 LOGMEM;
439 goto error;
440 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200441 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
442
443 /* get possible substatements */
444 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
445 goto error;
446 }
447 } else if (!strcmp(node->name, "fraction-digits")) {
448 if (type->info.dec64.dig) {
Radek Krejciadb57612016-02-16 13:34:34 +0100449 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200450 goto error;
451 }
452 GETVAL(value, node, "value");
453 v = strtol(value, NULL, 10);
454
455 /* range check */
456 if (v < 1 || v > 18) {
Radek Krejciadb57612016-02-16 13:34:34 +0100457 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200458 goto error;
459 }
460 type->info.dec64.dig = (uint8_t)v;
461 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100462 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200463 goto error;
464 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200465 }
466
467 /* mandatory sub-statement(s) check */
468 if (!type->info.dec64.dig && !type->der->type.der) {
469 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejciadb57612016-02-16 13:34:34 +0100470 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200471 goto error;
472 }
Radek Krejci7511f402015-07-10 09:56:30 +0200473 if (type->info.dec64.dig && type->der->type.der) {
474 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejciadb57612016-02-16 13:34:34 +0100475 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200476 goto error;
477 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200478 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200480 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200481 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200482
Radek Krejci994b6f62015-06-18 16:47:27 +0200483 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200485 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
486 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100487 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200488 continue;
489 }
490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200491 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200492 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200493 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100494 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200495 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200496 }
497 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200498 if (!type->der->type.der && !type->info.enums.count) {
499 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejciadb57612016-02-16 13:34:34 +0100500 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 goto error;
502 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200503 if (type->der->type.der && type->info.enums.count) {
504 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejciadb57612016-02-16 13:34:34 +0100505 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200506 goto error;
507 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200508
Radek Krejci1574a8d2015-08-03 14:16:52 +0200509 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100510 if (!type->info.enums.enm) {
511 LOGMEM;
512 goto error;
513 }
Radek Krejci73adb602015-07-02 18:07:40 +0200514 v = 0;
515 i = -1;
516 LY_TREE_FOR(yin->child, next) {
517 i++;
518
519 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100520 if (!value[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +0100521 LOGVAL(LYE_SPEC, LOGLINE(next), LY_VLOG_XML, next, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100522 goto error;
523 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200524 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200525 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200526 type->info.enums.count = i + 1;
527 goto error;
528 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200531 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200532 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejciadb57612016-02-16 13:34:34 +0100533 LOGVAL(LYE_ENUM_WS, LOGLINE(next), LY_VLOG_XML, next, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200534 type->info.enums.count = i + 1;
535 goto error;
536 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200538 /* check the name uniqueness */
539 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200540 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100541 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), LY_VLOG_XML, next, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200542 type->info.enums.count = i + 1;
543 goto error;
544 }
545 }
Radek Krejci04581c62015-05-22 21:24:00 +0200546
Radek Krejci0d70c372015-07-02 16:23:10 +0200547 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200548 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200549 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
550 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200551 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200552 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200553
Radek Krejci0d70c372015-07-02 16:23:10 +0200554 if (!strcmp(node->name, "value")) {
555 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200556 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200557
558 /* range check */
559 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100560 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200561 type->info.enums.count = i + 1;
562 goto error;
563 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200564 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200565
566 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200567 if (type->info.enums.enm[i].value > v) {
568 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200569 v++;
570 } else {
571 /* check that the value is unique */
572 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200573 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejciadb57612016-02-16 13:34:34 +0100574 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), LY_VLOG_XML, node,
575 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200576 type->info.enums.count = i + 1;
577 goto error;
578 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200579 }
580 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200581 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100582 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200583 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200585 }
586 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 /* assign value automatically */
588 if (v > INT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100589 LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_XML, next, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 type->info.enums.count = i + 1;
591 goto error;
592 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200593 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100594 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 v++;
596 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 }
598 break;
599
600 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200601 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602
603 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200604 LY_TREE_FOR_SAFE(yin->child, next, node) {
605 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
606 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100607 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200608 continue;
609 }
610
Michal Vaskoe29c6622015-11-27 15:02:31 +0100611 if (strcmp(node->name, "base")) {
Radek Krejciadb57612016-02-16 13:34:34 +0100612 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200613 goto error;
614 }
615 }
616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200617 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200618 if (type->der->type.der) {
619 /* this is just a derived type with no base specified/required */
620 break;
621 }
Radek Krejciadb57612016-02-16 13:34:34 +0100622 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 goto error;
624 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200625 if (yin->child->next) {
Radek Krejciadb57612016-02-16 13:34:34 +0100626 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), LY_VLOG_XML, yin->child->next,
627 yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 goto error;
629 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200630 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100631 /* store in the JSON format */
632 value = transform_schema2json(module, value, LOGLINE(yin->child));
633 if (!value) {
634 goto error;
635 }
Radek Krejcic5989d42016-02-17 11:16:38 +0100636 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child));
637 lydict_remove(module->ctx, value);
638
639 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200640 goto error;
641 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 break;
643
644 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200645 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200646 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200647 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
648 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200649 continue;
650 }
651
Radek Krejciaf351422015-06-19 14:49:38 +0200652 if (!strcmp(node->name, "require-instance")) {
653 if (type->info.inst.req) {
Radek Krejciadb57612016-02-16 13:34:34 +0100654 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200655 goto error;
656 }
657 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200658 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200659 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200660 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200661 type->info.inst.req = -1;
662 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100663 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200664 goto error;
665 }
666 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100667 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200668 goto error;
669 }
Radek Krejciaf351422015-06-19 14:49:38 +0200670 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200672 break;
673
Radek Krejcif2860132015-06-20 12:37:20 +0200674 case LY_TYPE_BINARY:
675 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200676 case LY_TYPE_INT8:
677 case LY_TYPE_INT16:
678 case LY_TYPE_INT32:
679 case LY_TYPE_INT64:
680 case LY_TYPE_UINT8:
681 case LY_TYPE_UINT16:
682 case LY_TYPE_UINT32:
683 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200684 /* RFC 6020 9.2.4 - range */
685
686 /* length and range are actually the same restriction, so process
687 * them by this common code, we just need to differ the name and
688 * structure where the information will be stored
689 */
690 if (type->base == LY_TYPE_BINARY) {
691 restr = &type->info.binary.length;
692 name = "length";
693 } else {
694 restr = &type->info.num.range;
695 name = "range";
696 }
697
Radek Krejci73adb602015-07-02 18:07:40 +0200698 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200699 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
700 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200701 continue;
702 }
703
Radek Krejcif2860132015-06-20 12:37:20 +0200704 if (!strcmp(node->name, name)) {
705 if (*restr) {
Radek Krejciadb57612016-02-16 13:34:34 +0100706 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200707 goto error;
708 }
709
710 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200711 if (lyp_check_length_range(value, type)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100712 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200713 goto error;
714 }
715 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100716 if (!(*restr)) {
717 LOGMEM;
718 goto error;
719 }
Radek Krejcif2860132015-06-20 12:37:20 +0200720 (*restr)->expr = lydict_insert(module->ctx, value, 0);
721
722 /* get possible substatements */
723 if (read_restr_substmt(module->ctx, *restr, node)) {
724 goto error;
725 }
726 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100727 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200728 goto error;
729 }
Radek Krejcif2860132015-06-20 12:37:20 +0200730 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200731 break;
732
733 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200734 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200735 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200736 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
737 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200738 continue;
739 }
740
Michal Vasko88c29542015-11-27 14:57:53 +0100741 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200742 if (type->info.lref.path) {
Radek Krejciadb57612016-02-16 13:34:34 +0100743 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200744 goto error;
745 }
746
747 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200748 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200749 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200750 if (!type->info.lref.path) {
751 goto error;
752 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200753 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200754 goto error;
755 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200756
Radek Krejcidc4c1412015-06-19 15:39:54 +0200757 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100758 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200759 goto error;
760 }
Radek Krejci73adb602015-07-02 18:07:40 +0200761 }
762
Michal Vasko88c29542015-11-27 14:57:53 +0100763 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejciadb57612016-02-16 13:34:34 +0100764 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200765 goto error;
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 Krejciadb57612016-02-16 13:34:34 +0100782 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, 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 Krejciadb57612016-02-16 13:34:34 +0100788 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, 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 Krejciadb57612016-02-16 13:34:34 +0100806 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, 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 Krejciadb57612016-02-16 13:34:34 +0100823 LOGVAL(LYE_INREGEX, LOGLINE(node), LY_VLOG_XML, node, 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 Krejciadb57612016-02-16 13:34:34 +0100855 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, 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 Krejciadb57612016-02-16 13:34:34 +0100865 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "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 Krejciadb57612016-02-16 13:34:34 +0100884 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, "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 Krejciadb57612016-02-16 13:34:34 +0100887 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, "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 Krejciadb57612016-02-16 13:34:34 +0100914 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, 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;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200941 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100944 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100945 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 goto error;
947 }
948 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100951 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 goto error;
953 }
Radek Krejcieac35532015-05-31 19:09:15 +0200954
Michal Vasko88c29542015-11-27 14:57:53 +0100955 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200956 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
957 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200958 continue;
959 }
960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200961 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100962 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +0100963 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 goto error;
965 }
Michal Vasko88c29542015-11-27 14:57:53 +0100966 /* HACK for unres */
967 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100968 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100969 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200970 goto error;
971 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200972 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 } else if (!strcmp(node->name, "default")) {
974 if (tpdf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +0100975 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200976 goto error;
977 }
978 GETVAL(value, node, "value");
979 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200980 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981 } else if (!strcmp(node->name, "units")) {
982 if (tpdf->units) {
Radek Krejciadb57612016-02-16 13:34:34 +0100983 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 goto error;
985 }
986 GETVAL(value, node, "name");
987 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
988 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100989 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 goto error;
991 }
992 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200995 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +0100996 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 goto error;
998 }
Radek Krejcieac35532015-05-31 19:09:15 +0200999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001001 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001002 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001003 goto error;
1004 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001005 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001007 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001008
1009error:
1010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001012}
1013
Michal Vasko0d343d12015-08-24 14:57:36 +02001014/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001015static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001016fill_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 +02001017{
1018 const char *value;
1019 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001020 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001021
Radek Krejcib05774c2015-06-18 13:52:59 +02001022 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01001023 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001024 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejcib05774c2015-06-18 13:52:59 +02001025 goto error;
1026 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001027 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001028 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001029
Radek Krejci76512572015-08-04 09:47:08 +02001030 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001031 goto error;
1032 }
1033
1034 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001035 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1036 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001037 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001038 continue;
1039 }
1040
Radek Krejci3cf9e222015-06-18 11:37:50 +02001041 if (!strcmp(child->name, "if-feature")) {
1042 c++;
1043 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001044 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001045 goto error;
1046 }
1047 }
1048
1049 if (c) {
1050 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001051 if (!f->features) {
1052 LOGMEM;
1053 goto error;
1054 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001055 }
Radek Krejci73adb602015-07-02 18:07:40 +02001056 LY_TREE_FOR(yin->child, child) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001057 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001058 f->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001059 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001060 goto error;
1061 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001062 }
1063
Radek Krejci3cf9e222015-06-18 11:37:50 +02001064 return EXIT_SUCCESS;
1065
1066error:
1067
1068 return EXIT_FAILURE;
1069}
1070
Michal Vasko0d343d12015-08-24 14:57:36 +02001071/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072static int
Radek Krejcib8048692015-08-05 13:36:34 +02001073fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001074{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001078 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001079 if (!must->expr) {
1080 goto error;
1081 }
Michal Vasko77dc5652016-02-15 12:32:42 +01001082 if (lyxp_syntax_check(must->expr, LOGLINE(yin))) {
1083 goto error;
1084 }
Radek Krejci800af702015-06-02 13:46:01 +02001085
Radek Krejci41726f92015-06-19 13:11:05 +02001086 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001087
Michal Vasko77dc5652016-02-15 12:32:42 +01001088error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001090}
1091
Radek Krejci581ce772015-11-10 17:22:40 +01001092static int
Michal Vasko88c29542015-11-27 14:57:53 +01001093fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1094 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001095{
1096 int i, j;
1097 const char *value, *vaux;
1098
1099 /* get unique value (list of leafs supposed to be unique */
1100 GETVAL(value, yin, "tag");
1101
1102 /* count the number of unique leafs in the value */
1103 vaux = value;
1104 while ((vaux = strpbrk(vaux, " \t\n"))) {
1105 unique->expr_size++;
1106 while (isspace(*vaux)) {
1107 vaux++;
1108 }
1109 }
1110 unique->expr_size++;
1111 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001112 if (!unique->expr) {
1113 LOGMEM;
1114 goto error;
1115 }
Radek Krejci581ce772015-11-10 17:22:40 +01001116
1117 for (i = 0; i < unique->expr_size; i++) {
1118 vaux = strpbrk(value, " \t\n");
1119 if (!vaux) {
1120 /* the last token, lydict_insert() will count its size on its own */
1121 vaux = value;
1122 }
1123
1124 /* store token into unique structure */
1125 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1126
1127 /* check that the expression does not repeat */
1128 for (j = 0; j < i; j++) {
Radek Krejciedaaa082016-02-17 10:21:54 +01001129 if (ly_strequal(unique->expr[j], unique->expr[i])) {
Radek Krejciadb57612016-02-16 13:34:34 +01001130 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, unique->expr[i], "unique");
1131 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001132 goto error;
1133 }
1134 }
1135
1136 /* try to resolve leaf */
1137 if (unres) {
1138 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1139 } else {
1140 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1141 goto error;
1142 }
1143 }
1144
1145 /* move to next token */
1146 value = vaux;
1147 while(isspace(*value)) {
1148 value++;
1149 }
1150 }
1151
1152 return EXIT_SUCCESS;
1153
1154error:
1155 return EXIT_FAILURE;
1156}
1157
Michal Vasko0d343d12015-08-24 14:57:36 +02001158/* logs directly
1159 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001160 * type: 0 - min, 1 - max
1161 */
1162static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001163deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001164{
1165 const char *value;
1166 char *endptr;
1167 unsigned long val;
1168 uint32_t *ui32val;
1169
1170 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001171 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001172 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001173 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001174 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001175 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001176 }
Radek Krejci76512572015-08-04 09:47:08 +02001177 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001178 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001179 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001180 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001181 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001182 }
1183 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001184 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
1185 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001186 goto error;
1187 }
1188
1189 GETVAL(value, node, "value");
1190 while (isspace(value[0])) {
1191 value++;
1192 }
1193
Radek Krejci0d7b2472016-02-12 11:11:03 +01001194 if (type && !strcmp(value, "unbounded")) {
1195 d->max = val = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001196 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001197 /* convert it to uint32_t */
1198 errno = 0;
1199 endptr = NULL;
1200 val = strtoul(value, &endptr, 10);
1201 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01001202 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001203 goto error;
1204 }
1205 if (type) {
1206 d->max = (uint32_t)val;
1207 } else {
1208 d->min = (uint32_t)val;
1209 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001210 }
1211
1212 if (d->mod == LY_DEVIATE_ADD) {
1213 /* check that there is no current value */
1214 if (*ui32val) {
Radek Krejciadb57612016-02-16 13:34:34 +01001215 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
1216 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001217 goto error;
1218 }
1219 }
1220
1221 if (d->mod == LY_DEVIATE_DEL) {
1222 /* check values */
1223 if ((uint32_t)val != *ui32val) {
Radek Krejciadb57612016-02-16 13:34:34 +01001224 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
1225 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001226 goto error;
1227 }
1228 /* remove current min-elements value of the target */
1229 *ui32val = 0;
1230 } else { /* add (already checked) and replace */
1231 /* set new value specified in deviation */
1232 *ui32val = (uint32_t)val;
1233 }
1234
1235 return EXIT_SUCCESS;
1236
1237error:
1238
1239 return EXIT_FAILURE;
1240}
1241
Michal Vasko0d343d12015-08-24 14:57:36 +02001242/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001243static int
Michal Vasko88c29542015-11-27 14:57:53 +01001244fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1245 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001246{
1247 const char *value, **stritem;
1248 struct lyxml_elem *next, *child, *develem;
1249 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001250 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001251 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001252 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001253 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001254 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001255 struct lys_node_choice *choice = NULL;
1256 struct lys_node_leaf *leaf = NULL;
1257 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001258 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001259 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001260 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001261
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001262 ctx = module->ctx;
1263
Radek Krejcieb00f512015-07-01 16:44:58 +02001264 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001265 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001266 if (!dev->target_name) {
1267 goto error;
1268 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001269
1270 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001271 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1272 if (rc || !dev_target) {
Radek Krejciadb57612016-02-16 13:34:34 +01001273 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001274 goto error;
1275 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001276 if (dev_target->module == module) {
Radek Krejciadb57612016-02-16 13:34:34 +01001277 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001278 goto error;
1279 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001280 dev->target_module = dev_target->module;
Radek Krejcieb00f512015-07-01 16:44:58 +02001281 /* mark the target module as deviated */
Michal Vasko60f4b452016-02-12 11:02:55 +01001282 dev->target_module->deviated = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001283
1284 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001285 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1286 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001287 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001288 continue;
1289 }
1290
Radek Krejcieb00f512015-07-01 16:44:58 +02001291 if (!strcmp(child->name, "description")) {
1292 if (dev->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01001293 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001294 goto error;
1295 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001296 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001297 if (!dev->dsc) {
1298 goto error;
1299 }
1300 } else if (!strcmp(child->name, "reference")) {
1301 if (dev->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01001302 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001303 goto error;
1304 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001305 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001306 if (!dev->ref) {
1307 goto error;
1308 }
1309 } else if (!strcmp(child->name, "deviate")) {
1310 c_dev++;
1311
Michal Vasko345da0a2015-12-02 10:35:55 +01001312 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001313 * further processed later
1314 */
1315 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001316
Radek Krejcieb00f512015-07-01 16:44:58 +02001317 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001318 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001319 goto error;
1320 }
1321
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001322 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001323 }
1324
1325 if (c_dev) {
1326 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001327 if (!dev->deviate) {
1328 LOGMEM;
1329 goto error;
1330 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001331 }
1332
1333 LY_TREE_FOR(yin->child, develem) {
1334 /* init */
1335 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001336 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001337 c_must = 0;
1338 c_uniq = 0;
1339
1340 /* get deviation type */
1341 GETVAL(value, develem, "value");
1342 if (!strcmp(value, "not-supported")) {
1343 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1344 /* no property expected in this case */
1345 if (develem->child) {
Radek Krejciadb57612016-02-16 13:34:34 +01001346 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), LY_VLOG_XML, develem->child, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001347 goto error;
1348 }
1349
Radek Krejci5b917642015-07-02 09:03:13 +02001350 /* and neither any other deviate statement is expected,
1351 * not-supported deviation must be the only deviation of the target
1352 */
1353 if (dev->deviate_size || develem->next) {
Radek Krejciadb57612016-02-16 13:34:34 +01001354 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
1355 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001356 goto error;
1357 }
1358
1359
Radek Krejcieb00f512015-07-01 16:44:58 +02001360 /* remove target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001361 lys_node_free(dev_target, NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02001362
Radek Krejci5b917642015-07-02 09:03:13 +02001363 dev->deviate_size = 1;
1364 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001365 } else if (!strcmp(value, "add")) {
1366 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1367 } else if (!strcmp(value, "replace")) {
1368 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1369 } else if (!strcmp(value, "delete")) {
1370 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1371 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001372 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 goto error;
1374 }
1375 d = &dev->deviate[dev->deviate_size];
1376
1377 /* process deviation properties */
1378 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001379 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1380 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001381 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001382 continue;
1383 }
1384
Radek Krejcieb00f512015-07-01 16:44:58 +02001385 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001386 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001387 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001388 goto error;
1389 }
1390
1391 /* for we deviate from RFC 6020 and allow config property even it is/is not
1392 * specified in the target explicitly since config property inherits. So we expect
1393 * that config is specified in every node. But for delete, we check that the value
1394 * is the same as here in deviation
1395 */
1396 GETVAL(value, child, "value");
1397 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001398 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001399 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001400 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001401 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001402 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001403 goto error;
1404 }
1405
1406 if (d->mod == LY_DEVIATE_DEL) {
1407 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001408 if ((d->flags & LYS_CONFIG_MASK) != (dev_target->flags & LYS_CONFIG_MASK)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001409 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1410 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001411 goto error;
1412 }
1413 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001414 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415
1416 /* ... and inherit config value from the target's parent */
Michal Vasko60f4b452016-02-12 11:02:55 +01001417 if (dev_target->parent) {
1418 dev_target->flags |= dev_target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001419 } else {
1420 /* default config is true */
Michal Vasko60f4b452016-02-12 11:02:55 +01001421 dev_target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001422 }
1423 } else { /* add and replace are the same in this case */
1424 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001425 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001426
1427 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001428 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001429 }
1430 } else if (!strcmp(child->name, "default")) {
1431 if (d->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001432 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001433 goto error;
1434 }
1435 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001436 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001437
Michal Vasko60f4b452016-02-12 11:02:55 +01001438 if (dev_target->nodetype == LYS_CHOICE) {
1439 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001440
1441 if (d->mod == LY_DEVIATE_ADD) {
1442 /* check that there is no current value */
1443 if (choice->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001444 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1445 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001446 goto error;
1447 }
1448 }
1449
Michal Vasko3edeaf72016-02-11 13:17:43 +01001450 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001451 if (rc || !node) {
Radek Krejciadb57612016-02-16 13:34:34 +01001452 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001453 goto error;
1454 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001455 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001456 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001457 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1458 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001459 goto error;
1460 }
1461 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001462 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001463 if (!choice->dflt) {
1464 /* default branch not found */
Radek Krejciadb57612016-02-16 13:34:34 +01001465 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001466 goto error;
1467 }
1468 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001469 } else if (dev_target->nodetype == LYS_LEAF) {
1470 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001471
1472 if (d->mod == LY_DEVIATE_ADD) {
1473 /* check that there is no current value */
1474 if (leaf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001475 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1476 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001477 goto error;
1478 }
1479 }
1480
1481 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001482 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001483 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1484 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001485 goto error;
1486 }
1487 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001488 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001489 leaf->dflt = NULL;
1490 } else { /* add (already checked) and replace */
1491 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001492 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001493
1494 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001495 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001496 }
1497 } else {
1498 /* invalid target for default value */
Radek Krejciadb57612016-02-16 13:34:34 +01001499 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1500 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001501 goto error;
1502 }
1503 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001504 if (d->flags & LYS_MAND_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001505 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001506 goto error;
1507 }
1508
1509 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001510 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejciadb57612016-02-16 13:34:34 +01001511 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1512 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 goto error;
1514 }
1515
1516 GETVAL(value, child, "value");
1517 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001518 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001520 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001521 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001522 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001523 goto error;
1524 }
1525
1526 if (d->mod == LY_DEVIATE_ADD) {
1527 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001528 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001529 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1530 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001531 goto error;
1532 }
1533 }
1534
1535 if (d->mod == LY_DEVIATE_DEL) {
1536 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001537 if ((d->flags & LYS_MAND_MASK) != (dev_target->flags & LYS_MAND_MASK)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001538 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1539 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001540 goto error;
1541 }
1542 /* remove current mandatory value of the target */
Michal Vasko60f4b452016-02-12 11:02:55 +01001543 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 } else { /* add (already checked) and replace */
1545 /* remove current mandatory value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001546 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001547
1548 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001549 dev_target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 }
1551 } else if (!strcmp(child->name, "min-elements")) {
1552 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01001553 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 goto error;
1555 }
1556 f_min = 1;
1557
Michal Vasko60f4b452016-02-12 11:02:55 +01001558 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001559 goto error;
1560 }
1561 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001562 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01001563 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001564 goto error;
1565 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001566 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001567
Michal Vasko60f4b452016-02-12 11:02:55 +01001568 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001569 goto error;
1570 }
1571 } else if (!strcmp(child->name, "must")) {
1572 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001573 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001574 continue;
1575 } else if (!strcmp(child->name, "type")) {
1576 if (d->type) {
Radek Krejciadb57612016-02-16 13:34:34 +01001577 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001578 goto error;
1579 }
1580
1581 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001582 if (dev_target->nodetype == LYS_LEAF) {
1583 t = &((struct lys_node_leaf *)dev_target)->type;
1584 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1585 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001586 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001587 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1588 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001589 goto error;
1590 }
1591
1592 if (d->mod == LY_DEVIATE_ADD) {
1593 /* not allowed, type is always present at the target */
Radek Krejciadb57612016-02-16 13:34:34 +01001594 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1595 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001596 goto error;
1597 } else if (d->mod == LY_DEVIATE_DEL) {
1598 /* not allowed, type cannot be deleted from the target */
Radek Krejciadb57612016-02-16 13:34:34 +01001599 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1600 LOGVAL(LYE_SPEC, 0, 0, NULL, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001601 goto error;
1602 }
1603
1604 /* replace */
1605 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001606 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001607
1608 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001609 /* HACK for unres */
1610 t->der = (struct lys_tpdf *)child;
Michal Vasko60f4b452016-02-12 11:02:55 +01001611 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001612 goto error;
1613 }
1614 d->type = t;
1615 } else if (!strcmp(child->name, "unique")) {
1616 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001617 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001618 continue;
1619 } else if (!strcmp(child->name, "units")) {
1620 if (d->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01001621 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 goto error;
1623 }
1624
1625 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001626 if (dev_target->nodetype == LYS_LEAFLIST) {
1627 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1628 } else if (dev_target->nodetype == LYS_LEAF) {
1629 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001630 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001631 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1632 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001633 goto error;
1634 }
1635
1636 /* get units value */
1637 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001638 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001639
1640 /* apply to target */
1641 if (d->mod == LY_DEVIATE_ADD) {
1642 /* check that there is no current value */
1643 if (*stritem) {
Radek Krejciadb57612016-02-16 13:34:34 +01001644 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1645 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 goto error;
1647 }
1648 }
1649
1650 if (d->mod == LY_DEVIATE_DEL) {
1651 /* check values */
1652 if (*stritem != d->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01001653 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1654 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001655 goto error;
1656 }
1657 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001658 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001659 } else { /* add (already checked) and replace */
1660 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001661 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001662
1663 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001664 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 }
1666 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001667 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001668 goto error;
1669 }
1670
Michal Vasko88c29542015-11-27 14:57:53 +01001671 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001672 }
1673
1674 if (c_must) {
1675 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001676 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001677 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001678 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1679 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001680 break;
Radek Krejci76512572015-08-04 09:47:08 +02001681 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001682 trg_must = &((struct lys_node_container *)dev_target)->must;
1683 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001684 break;
Radek Krejci76512572015-08-04 09:47:08 +02001685 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001686 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1687 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001688 break;
Radek Krejci76512572015-08-04 09:47:08 +02001689 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001690 trg_must = &((struct lys_node_list *)dev_target)->must;
1691 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 break;
Radek Krejci76512572015-08-04 09:47:08 +02001693 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001694 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1695 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001696 break;
1697 default:
Radek Krejciadb57612016-02-16 13:34:34 +01001698 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1699 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001700 goto error;
1701 }
1702
1703 if (d->mod == LY_DEVIATE_RPL) {
1704 /* remove target's musts and allocate new array for it */
1705 if (!*trg_must) {
Radek Krejciadb57612016-02-16 13:34:34 +01001706 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, "replace", "deviate");
1707 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001708 goto error;
1709 }
1710
1711 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001712 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 }
1714 free(*trg_must);
1715 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1716 d->must_size = c_must;
1717 *trg_must_size = 0;
1718 } else if (d->mod == LY_DEVIATE_ADD) {
1719 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001720 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001721 if (!d->must) {
1722 LOGMEM;
1723 goto error;
1724 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001726 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 d->must_size = c_must;
1728 } else { /* LY_DEVIATE_DEL */
1729 d->must = calloc(c_must, sizeof *d->must);
1730 }
Michal Vasko253035f2015-12-17 16:58:13 +01001731 if (!d->must) {
1732 LOGMEM;
1733 goto error;
1734 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001735 }
1736 if (c_uniq) {
1737 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001738 if (dev_target->nodetype != LYS_LIST) {
Radek Krejciadb57612016-02-16 13:34:34 +01001739 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1740 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 goto error;
1742 }
1743
Michal Vasko60f4b452016-02-12 11:02:55 +01001744 list = (struct lys_node_list *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001745 if (d->mod == LY_DEVIATE_RPL) {
1746 /* remove target's unique and allocate new array for it */
1747 if (!list->unique) {
Radek Krejciadb57612016-02-16 13:34:34 +01001748 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, "replace", "deviate");
1749 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001750 goto error;
1751 }
1752
1753 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001754 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001755 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001756 }
1757 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001758 }
1759 free(list->unique);
1760 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1761 d->unique_size = c_uniq;
1762 list->unique_size = 0;
1763 } else if (d->mod == LY_DEVIATE_ADD) {
1764 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001765 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001766 list->unique = d->unique;
1767 d->unique = &list->unique[list->unique_size];
1768 d->unique_size = c_uniq;
1769 } else { /* LY_DEVIATE_DEL */
1770 d->unique = calloc(c_uniq, sizeof *d->unique);
1771 }
Michal Vasko253035f2015-12-17 16:58:13 +01001772 if (!d->unique) {
1773 LOGMEM;
1774 goto error;
1775 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001776 }
1777
1778 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001779 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001780 if (!strcmp(child->name, "must")) {
1781 if (d->mod == LY_DEVIATE_DEL) {
1782 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1783 goto error;
1784 }
1785
1786 /* find must to delete, we are ok with just matching conditions */
1787 for (i = 0; i < *trg_must_size; i++) {
Radek Krejciedaaa082016-02-17 10:21:54 +01001788 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001789 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001790 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 /* ... and maintain the array */
1792 (*trg_must_size)--;
1793 if (i != *trg_must_size) {
1794 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1795 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1796 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1797 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1798 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1799 }
1800 if (!(*trg_must_size)) {
1801 free(*trg_must);
1802 *trg_must = NULL;
1803 } else {
1804 (*trg_must)[*trg_must_size].expr = NULL;
1805 (*trg_must)[*trg_must_size].dsc = NULL;
1806 (*trg_must)[*trg_must_size].ref = NULL;
1807 (*trg_must)[*trg_must_size].eapptag = NULL;
1808 (*trg_must)[*trg_must_size].emsg = NULL;
1809 }
1810
1811 i = -1; /* set match flag */
1812 break;
1813 }
1814 }
1815 d->must_size++;
1816 if (i != -1) {
1817 /* no match found */
Radek Krejciadb57612016-02-16 13:34:34 +01001818 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child,
1819 d->must[d->must_size - 1].expr, child->name);
1820 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001821 goto error;
1822 }
1823 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001824 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1825 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001826 goto error;
1827 }
1828 (*trg_must_size)++;
1829 }
1830 } else if (!strcmp(child->name, "unique")) {
1831 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001832 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001833 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001834 goto error;
1835 }
1836
1837 /* find unique structures to delete */
1838 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001839 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001840 continue;
1841 }
1842
Radek Krejci581ce772015-11-10 17:22:40 +01001843 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01001844 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j])) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001845 break;
1846 }
1847 }
1848
Radek Krejci581ce772015-11-10 17:22:40 +01001849 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001850 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001851 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001852 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001853 }
1854 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 /* ... and maintain the array */
1856 list->unique_size--;
1857 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001858 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1859 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001860 }
1861
1862 if (!list->unique_size) {
1863 free(list->unique);
1864 list->unique = NULL;
1865 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001866 list->unique[list->unique_size].expr_size = 0;
1867 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001868 }
1869
1870 i = -1; /* set match flag */
1871 break;
1872 }
1873 }
1874
1875 d->unique_size++;
1876 if (i != -1) {
1877 /* no match found */
Radek Krejciadb57612016-02-16 13:34:34 +01001878 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, lyxml_get_attr(child, "tag", NULL), child->name);
1879 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001880 goto error;
1881 }
1882 } else { /* replace or add */
Michal Vasko60f4b452016-02-12 11:02:55 +01001883 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001884 list->unique_size++;
1885 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001886 goto error;
1887 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001888 }
1889 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001890 }
Radek Krejci5b917642015-07-02 09:03:13 +02001891
1892 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001893 }
1894
Radek Krejcieb00f512015-07-01 16:44:58 +02001895 return EXIT_SUCCESS;
1896
1897error:
1898
Radek Krejcieb00f512015-07-01 16:44:58 +02001899 return EXIT_FAILURE;
1900}
1901
Michal Vasko0d343d12015-08-24 14:57:36 +02001902/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001903static int
Radek Krejcib8048692015-08-05 13:36:34 +02001904fill_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 +02001905 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001906{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001908 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001909 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001910 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001911
Michal Vasko591e0b22015-08-13 13:53:43 +02001912 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001914 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001915 if (!aug->target_name) {
1916 goto error;
1917 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001919
Michal Vasko1d87a922015-08-21 12:57:16 +02001920 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001921 goto error;
1922 }
1923
1924 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001925 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1926 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001927 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001928 continue;
1929 }
1930
Radek Krejci3cf9e222015-06-18 11:37:50 +02001931 if (!strcmp(child->name, "if-feature")) {
1932 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001933 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001934 } else if (!strcmp(child->name, "when")) {
1935 if (aug->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01001936 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001937 goto error;
1938 }
1939
1940 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001941 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001942 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001943 goto error;
1944 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001945 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001946 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001947
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001948 /* check allowed data sub-statements */
1949 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001950 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001951 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001952 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001953 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001956 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001957 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001958 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001959 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001960 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001961 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001962 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001963 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001964 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001965 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001966 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001967 goto error;
1968 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001969
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001971 goto error;
1972 }
1973
1974 /* check for mandatory nodes - if the target node is in another module
1975 * the added nodes cannot be mandatory
1976 */
Radek Krejcic6556022016-01-27 15:16:45 +01001977 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001978 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child,
1979 "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980 goto error;
1981 }
1982
Radek Krejci1d82ef62015-08-07 14:44:40 +02001983 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001984 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001985 }
1986
1987 if (c) {
1988 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001989 if (!aug->features) {
1990 LOGMEM;
1991 goto error;
1992 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001993 }
1994
1995 LY_TREE_FOR_SAFE(yin->child, next, child) {
1996 if (!strcmp(child->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01001997 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001998 aug->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001999 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002000 goto error;
2001 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002002 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002003 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002004 }
2005
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002007 * connected to the tree and adjusted (if possible right now).
2008 * However, if this is augment in a uses, it gets resolved
2009 * when the uses does and cannot be resolved now for sure
2010 * (the grouping was not yet copied into uses).
2011 */
2012 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko7178e692016-02-12 15:58:05 +01002013 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin)) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002014 goto error;
2015 }
Michal Vasko49291b32015-08-06 09:49:41 +02002016 }
Radek Krejci106efc02015-06-10 14:36:27 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002019
2020error:
2021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002022 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002023}
2024
Michal Vasko0d343d12015-08-24 14:57:36 +02002025/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026static int
Michal Vasko0d204592015-10-07 09:50:04 +02002027fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002028{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 struct lyxml_elem *sub, *next;
2030 const char *value;
2031 char *endptr;
2032 int f_mand = 0, f_min = 0, f_max = 0;
2033 int c_must = 0;
2034 int r;
2035 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002036
Radek Krejci76512572015-08-04 09:47:08 +02002037 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 goto error;
2039 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002040
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002041 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002042 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002043 if (!rfn->target_name) {
2044 goto error;
2045 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002048 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2049 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002050 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002051 continue;
2052 }
2053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054 /* limited applicability */
2055 if (!strcmp(sub->name, "default")) {
2056 /* leaf or choice */
2057 if (rfn->mod.dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01002058 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 goto error;
2060 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 /* check possibility of statements combination */
2063 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002064 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002066 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 goto error;
2068 }
2069 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002070 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 GETVAL(value, sub, "value");
2074 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2075 } else if (!strcmp(sub->name, "mandatory")) {
2076 /* leaf, choice or anyxml */
2077 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002078 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 goto error;
2080 }
2081 /* just checking the flags in leaf is not sufficient, we would allow
2082 * multiple mandatory statements with the "false" value
2083 */
2084 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 /* check possibility of statements combination */
2087 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002088 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002090 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 goto error;
2092 }
2093 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002094 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 GETVAL(value, sub, "value");
2098 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002099 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002101 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002103 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 goto error;
2105 }
2106 } else if (!strcmp(sub->name, "min-elements")) {
2107 /* list or leaf-list */
2108 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01002109 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 goto error;
2111 }
2112 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 /* check possibility of statements combination */
2115 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002116 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002118 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 goto error;
2120 }
2121 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002122 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 GETVAL(value, sub, "value");
2126 while (isspace(value[0])) {
2127 value++;
2128 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 /* convert it to uint32_t */
2131 errno = 0;
2132 endptr = NULL;
2133 val = strtoul(value, &endptr, 10);
2134 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01002135 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 goto error;
2137 }
2138 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 /* magic - bit 3 in flags means min set */
2141 rfn->flags |= 0x04;
2142 } else if (!strcmp(sub->name, "max-elements")) {
2143 /* list or leaf-list */
2144 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01002145 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 goto error;
2147 }
2148 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 /* check possibility of statements combination */
2151 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002152 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002154 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 goto error;
2156 }
2157 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002158 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 GETVAL(value, sub, "value");
2162 while (isspace(value[0])) {
2163 value++;
2164 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002165
Radek Krejci0d7b2472016-02-12 11:11:03 +01002166 if (!strcmp(value, "unbounded")) {
2167 rfn->mod.list.max = 0;
2168 } else {
2169 /* convert it to uint32_t */
2170 errno = 0;
2171 endptr = NULL;
2172 val = strtoul(value, &endptr, 10);
2173 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01002174 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002175 goto error;
2176 }
2177 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 /* magic - bit 4 in flags means min set */
2181 rfn->flags |= 0x08;
2182 } else if (!strcmp(sub->name, "presence")) {
2183 /* container */
2184 if (rfn->mod.presence) {
Radek Krejciadb57612016-02-16 13:34:34 +01002185 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 goto error;
2187 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 /* check possibility of statements combination */
2190 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002191 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002193 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine 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_CONTAINER;
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 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2202 } else if (!strcmp(sub->name, "must")) {
2203 /* leaf-list, list, container or anyxml */
2204 /* check possibility of statements combination */
2205 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002206 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002208 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 goto error;
2210 }
2211 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002212 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002216 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002219 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 goto error;
2221 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002222
Michal Vasko345da0a2015-12-02 10:35:55 +01002223 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 /* process nodes with cardinality of 0..n */
2227 if (c_must) {
2228 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002229 if (!rfn->must) {
2230 LOGMEM;
2231 goto error;
2232 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 }
Radek Krejci73adb602015-07-02 18:07:40 +02002234 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002235 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2236 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002237 if (r) {
2238 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002243
2244error:
2245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002247}
2248
Michal Vasko0d343d12015-08-24 14:57:36 +02002249/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250static int
Radek Krejcib8048692015-08-05 13:36:34 +02002251fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002252{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 struct lyxml_elem *child;
2254 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002255 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002258 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2259 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002260 continue;
2261 }
2262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 if (!strcmp(child->name, "prefix")) {
2264 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002265 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002266 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002267 goto error;
2268 }
2269 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2270 } else if (!strcmp(child->name, "revision-date")) {
2271 if (imp->rev[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +01002272 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 goto error;
2274 }
2275 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002276 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01002277 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 goto error;
2279 }
2280 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2281 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002282 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 goto error;
2284 }
2285 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 /* check mandatory information */
2288 if (!imp->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01002289 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 goto error;
2291 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002294
2295 /* check for circular import, store it if passed */
2296 if (!module->ctx->models.parsing) {
2297 count = 0;
2298 } else {
2299 for (count = 0; module->ctx->models.parsing[count]; ++count) {
Radek Krejciedaaa082016-02-17 10:21:54 +01002300 if (ly_strequal(value, module->ctx->models.parsing[count])) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002301 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2302 goto error;
2303 }
2304 }
2305 }
2306 ++count;
2307 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002308 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2309 if (!module->ctx->models.parsing) {
2310 LOGMEM;
2311 goto error;
2312 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002313 module->ctx->models.parsing[count - 1] = value;
2314 module->ctx->models.parsing[count] = NULL;
2315
2316 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002317 imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002319 /* whether to use a user callback is decided in the function */
2320 imp->module = (struct lys_module *)ly_ctx_load_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002321 }
2322
2323 /* remove the new module name now that its parsing is finished (even if failed) */
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01002324 if (module->ctx->models.parsing[count] || !ly_strequal(module->ctx->models.parsing[count - 1], value)) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002325 LOGINT;
2326 }
2327 --count;
2328 if (count) {
2329 module->ctx->models.parsing[count] = NULL;
2330 } else {
2331 free(module->ctx->models.parsing);
2332 module->ctx->models.parsing = NULL;
2333 }
2334
2335 /* check the result */
2336 if (!imp->module) {
Radek Krejciadb57612016-02-16 13:34:34 +01002337 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002338 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2339 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002343
2344error:
2345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002347}
2348
Michal Vasko0d343d12015-08-24 14:57:36 +02002349/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002351fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2352 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002353{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 struct lyxml_elem *child;
2355 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002356 char *module_data;
2357 void (*module_data_free)(char *module_data) = NULL;
2358 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko2e7241e2016-02-15 16:06:34 +01002359 int count, i, ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02002360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002362 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2363 /* garbage */
2364 continue;
2365 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 if (!strcmp(child->name, "revision-date")) {
2367 if (inc->rev[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +01002368 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 goto error;
2370 }
2371 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002372 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01002373 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 goto error;
2375 }
2376 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2377 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002378 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002379 goto error;
2380 }
2381 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002384
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002385 /* check that the submodule was not included yet (previous submodule could have included it) */
2386 for (i = 0; i < module->inc_size; ++i) {
Radek Krejciedaaa082016-02-17 10:21:54 +01002387 if (module->inc[i].submodule && (ly_strequal(module->inc[i].submodule->name, value))) {
Michal Vasko5ff78822016-02-12 09:33:31 +01002388 /* copy the duplicate into the result */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002389 memcpy(inc, &module->inc[i], sizeof *inc);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002390
Michal Vasko5ff78822016-02-12 09:33:31 +01002391 if (submodule) {
2392 /* we don't care if it was external or not */
2393 inc->external = 0;
2394 } else if (inc->external) {
2395 /* remove the duplicate */
2396 --module->inc_size;
2397 memmove(&module->inc[i], &module->inc[i + 1], (module->inc_size - i) * sizeof *inc);
2398 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
2399
2400 /* it is no longer external */
2401 inc->external = 0;
2402 }
2403 /* if !submodule && !inc->external, we just create a duplicate so it is detected and ended with error */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002404
2405 return EXIT_SUCCESS;
2406 }
2407 }
2408
Michal Vasko1b882eb2015-10-22 11:43:14 +02002409 /* check for circular include, store it if passed */
2410 if (!module->ctx->models.parsing) {
2411 count = 0;
2412 } else {
2413 for (count = 0; module->ctx->models.parsing[count]; ++count) {
Radek Krejciedaaa082016-02-17 10:21:54 +01002414 if (ly_strequal(value, module->ctx->models.parsing[count])) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002415 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2416 goto error;
2417 }
2418 }
2419 }
2420 ++count;
2421 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002422 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2423 if (!module->ctx->models.parsing) {
2424 LOGMEM;
2425 goto error;
2426 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002427 module->ctx->models.parsing[count - 1] = value;
2428 module->ctx->models.parsing[count] = NULL;
2429
2430 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002431 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002433 if (module->ctx->module_clb) {
2434 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2435 &format, &module_data_free);
2436 if (module_data) {
Michal Vasko2e7241e2016-02-15 16:06:34 +01002437 ret = lys_submodule_parse(module, module_data, format, unres, &inc->submodule);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002438 if (module_data_free) {
2439 module_data_free(module_data);
2440 } else {
2441 free(module_data);
2442 }
2443 } else {
2444 LOGERR(LY_EVALID, "User module retrieval callback failed!");
Michal Vasko7a17a462016-02-16 11:11:39 +01002445 ret = -1;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002446 }
2447 } else {
Michal Vasko2e7241e2016-02-15 16:06:34 +01002448 ret = lyp_search_file(module->ctx, module, value, inc->rev[0] ? inc->rev : NULL, unres,
2449 (struct lys_module **)&inc->submodule);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002450 }
Michal Vasko7a17a462016-02-16 11:11:39 +01002451 } else {
2452 ret = 0;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002453 }
2454
2455 /* remove the new submodule name now that its parsing is finished (even if failed) */
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01002456 if (module->ctx->models.parsing[count] || !ly_strequal(module->ctx->models.parsing[count - 1], value)) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002457 LOGINT;
2458 }
2459 --count;
2460 if (count) {
2461 module->ctx->models.parsing[count] = NULL;
2462 } else {
2463 free(module->ctx->models.parsing);
2464 module->ctx->models.parsing = NULL;
2465 }
2466
2467 /* check the result */
Michal Vasko2e7241e2016-02-15 16:06:34 +01002468 if (ret) {
Radek Krejciadb57612016-02-16 13:34:34 +01002469 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002470 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2471 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002472 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002474 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002475
2476error:
2477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002479}
2480
Michal Vasko0d343d12015-08-24 14:57:36 +02002481/* logs directly
2482 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002483 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002484 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002485 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002486 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487static int
Radek Krejcib8048692015-08-05 13:36:34 +02002488read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002489 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002490{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 const char *value;
2492 struct lyxml_elem *sub, *next;
2493 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002496 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002497 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 if (opt & OPT_IDENT) {
2500 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002501 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002502 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, xmlnode);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 goto error;
2504 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002505 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002506 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002507
Radek Krejci6764bb32015-07-03 15:16:04 +02002508 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002509 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002510 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002511 }
2512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 /* process local parameters */
2514 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002515 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002516 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002517 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002518 continue;
2519 }
2520 if (strcmp(sub->ns->value, LY_NSYIN)) {
2521 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002522 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002523 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002524 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002525 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002526 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002527 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002528 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002529 goto error;
2530 }
2531 }
2532
2533 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002534 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002535 continue;
2536 }
2537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002539 if (node->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01002540 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 goto error;
2542 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002543 node->dsc = read_yin_subnode(ctx, sub, "text");
2544 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002545 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 }
2547 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002548 if (node->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01002549 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 goto error;
2551 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002552 node->ref = read_yin_subnode(ctx, sub, "text");
2553 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002554 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 }
2556 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002557 if (node->flags & LYS_STATUS_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01002558 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002559 goto error;
2560 }
2561 GETVAL(value, sub, "value");
2562 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002563 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002565 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002566 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002567 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002568 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002569 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002570 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 }
2572 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002573 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01002574 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 goto error;
2576 }
2577 GETVAL(value, sub, "value");
2578 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002579 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002581 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002583 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002584 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 }
2586 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002587 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002588 continue;
2589 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002590 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002591 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002592
Radek Krejci1d82ef62015-08-07 14:44:40 +02002593 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 /* get config flag from parent */
2595 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002596 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 } else {
2598 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002599 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 }
2601 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002603 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002604
2605error:
2606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002608}
2609
Michal Vasko0d343d12015-08-24 14:57:36 +02002610/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002611static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002612read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002613{
Radek Krejci76512572015-08-04 09:47:08 +02002614 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002615 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002616 const char *value;
2617
2618 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002619 if (!retval) {
2620 LOGMEM;
2621 return NULL;
2622 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002623
2624 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002625 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002626 if (!retval->cond) {
2627 goto error;
2628 }
Michal Vasko77dc5652016-02-15 12:32:42 +01002629 if (lyxp_syntax_check(retval->cond, LOGLINE(yin))) {
2630 goto error;
2631 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002632
Radek Krejci73adb602015-07-02 18:07:40 +02002633 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002634 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2635 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002636 continue;
2637 }
2638
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002639 if (!strcmp(child->name, "description")) {
2640 if (retval->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01002641 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002642 goto error;
2643 }
2644 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2645 if (!retval->dsc) {
2646 goto error;
2647 }
2648 } else if (!strcmp(child->name, "reference")) {
2649 if (retval->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01002650 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002651 goto error;
2652 }
2653 retval->ref = read_yin_subnode(module->ctx, child, "text");
2654 if (!retval->ref) {
2655 goto error;
2656 }
2657 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002658 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002659 goto error;
2660 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002661 }
2662
2663 return retval;
2664
2665error:
2666
Michal Vasko0308dd62015-10-07 09:14:40 +02002667 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002668 return NULL;
2669}
2670
Michal Vasko0d343d12015-08-24 14:57:36 +02002671/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002672static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002673read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2674 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002675{
Michal Vasko29fc0182015-08-24 15:02:39 +02002676 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002677 struct lys_node_case *cs;
2678 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002679 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002680
Radek Krejcie867c852015-08-27 09:52:34 +02002681 /* init */
2682 memset(&root, 0, sizeof root);
2683
Radek Krejci1d82ef62015-08-07 14:44:40 +02002684 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002685 if (!cs) {
2686 LOGMEM;
2687 return NULL;
2688 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002689 cs->nodetype = LYS_CASE;
2690 cs->prev = (struct lys_node *)cs;
2691 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002692
Radek Krejci6a113852015-07-03 16:04:20 +02002693 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002694 goto error;
2695 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002696
Radek Krejcia9544502015-08-14 08:24:29 +02002697 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2698
Michal Vasko3a0043f2015-08-12 12:11:30 +02002699 /* insert the node into the schema tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +01002700 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002701 goto error;
2702 }
2703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002704 /* process choice's specific children */
2705 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002706 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2707 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002708 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002709 continue;
2710 }
2711
Michal Vasko29fc0182015-08-24 15:02:39 +02002712 if (!strcmp(sub->name, "container") ||
2713 !strcmp(sub->name, "leaf-list") ||
2714 !strcmp(sub->name, "leaf") ||
2715 !strcmp(sub->name, "list") ||
2716 !strcmp(sub->name, "uses") ||
2717 !strcmp(sub->name, "choice") ||
2718 !strcmp(sub->name, "anyxml")) {
2719
Michal Vaskof3930de2015-10-22 12:03:59 +02002720 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002721 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002722 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002723 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002724 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002725 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002726 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002727 if (cs->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002728 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002729 goto error;
2730 }
2731
Radek Krejci1d82ef62015-08-07 14:44:40 +02002732 cs->when = read_yin_when(module, sub);
2733 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002734 goto error;
2735 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002736
Michal Vasko345da0a2015-12-02 10:35:55 +01002737 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002739 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002742 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002743
Radek Krejci3cf9e222015-06-18 11:37:50 +02002744 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002745 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002746 if (!cs->features) {
2747 LOGMEM;
2748 goto error;
2749 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002750 }
Radek Krejci73adb602015-07-02 18:07:40 +02002751 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002752 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002753 cs->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002754 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002755 goto error;
2756 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 }
Radek Krejcib388c152015-06-04 17:03:03 +02002758
Michal Vasko29fc0182015-08-24 15:02:39 +02002759 /* last part - process data nodes */
2760 LY_TREE_FOR_SAFE(root.child, next, sub) {
2761 if (!strcmp(sub->name, "container")) {
2762 node = read_yin_container(module, retval, sub, resolve, unres);
2763 } else if (!strcmp(sub->name, "leaf-list")) {
2764 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2765 } else if (!strcmp(sub->name, "leaf")) {
2766 node = read_yin_leaf(module, retval, sub, resolve, unres);
2767 } else if (!strcmp(sub->name, "list")) {
2768 node = read_yin_list(module, retval, sub, resolve, unres);
2769 } else if (!strcmp(sub->name, "choice")) {
2770 node = read_yin_choice(module, retval, sub, resolve, unres);
2771 } else if (!strcmp(sub->name, "uses")) {
2772 node = read_yin_uses(module, retval, sub, resolve, unres);
2773 } else if (!strcmp(sub->name, "anyxml")) {
2774 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2775 }
2776 if (!node) {
2777 goto error;
2778 }
2779
Michal Vasko345da0a2015-12-02 10:35:55 +01002780 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002781 }
2782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002784
2785error:
2786
Michal Vasko29fc0182015-08-24 15:02:39 +02002787 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002788 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002789 }
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002790 lys_node_free(retval, NULL);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002793}
2794
Michal Vasko0d343d12015-08-24 14:57:36 +02002795/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002796static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002797read_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 +02002798{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 struct lyxml_elem *sub, *next;
2800 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002801 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002802 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002803 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002804 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002806 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002807 if (!choice) {
2808 LOGMEM;
2809 return NULL;
2810 }
Radek Krejci76512572015-08-04 09:47:08 +02002811 choice->nodetype = LYS_CHOICE;
2812 choice->prev = (struct lys_node *)choice;
2813 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002814
Michal Vaskoe0c59842015-09-24 13:52:20 +02002815 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2816 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002817 goto error;
2818 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002819
Radek Krejcia9544502015-08-14 08:24:29 +02002820 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2821
Michal Vasko3a0043f2015-08-12 12:11:30 +02002822 /* insert the node into the schema tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +01002823 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002824 goto error;
2825 }
2826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002827 /* process choice's specific children */
2828 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002829 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2830 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002831 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002832 continue;
2833 }
2834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002835 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002836 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 goto error;
2838 }
2839 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002840 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 goto error;
2842 }
2843 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002844 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002845 goto error;
2846 }
2847 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002848 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 goto error;
2850 }
2851 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002852 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 goto error;
2854 }
2855 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002856 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 goto error;
2858 }
2859 } else if (!strcmp(sub->name, "default")) {
2860 if (dflt_str) {
Radek Krejciadb57612016-02-16 13:34:34 +01002861 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 goto error;
2863 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002864 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002865 } else if (!strcmp(sub->name, "mandatory")) {
2866 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002867 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002868 goto error;
2869 }
2870 /* just checking the flags in leaf is not sufficient, we would allow
2871 * multiple mandatory statements with the "false" value
2872 */
2873 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 GETVAL(value, sub, "value");
2876 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002877 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002878 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002879 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002880 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002881 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002882 goto error;
2883 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002884 } else if (!strcmp(sub->name, "when")) {
2885 if (choice->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002886 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002887 goto error;
2888 }
2889
2890 choice->when = read_yin_when(module, sub);
2891 if (!choice->when) {
2892 goto error;
2893 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002894 } else if (!strcmp(sub->name, "if-feature")) {
2895 c_ftrs++;
2896
Michal Vasko345da0a2015-12-02 10:35:55 +01002897 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002898 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002900 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002901 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002903
Radek Krejci1d82ef62015-08-07 14:44:40 +02002904 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002905 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002907
Radek Krejci3cf9e222015-06-18 11:37:50 +02002908 if (c_ftrs) {
2909 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002910 if (!choice->features) {
2911 LOGMEM;
2912 goto error;
2913 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002914 }
2915
Radek Krejci73adb602015-07-02 18:07:40 +02002916 LY_TREE_FOR(yin->child, sub) {
Michal Vasko1d337e12016-02-15 12:32:04 +01002917 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002918 choice->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002919 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002920 goto error;
2921 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002922 }
2923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002925 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002926 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2928 goto error;
2929 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931 /* link default with the case */
2932 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002933 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002934 goto error;
2935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002938 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002939
2940error:
2941
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002942 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002945}
2946
Michal Vasko0d343d12015-08-24 14:57:36 +02002947/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002948static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002949read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002950 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002951{
Radek Krejci76512572015-08-04 09:47:08 +02002952 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002953 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002954 struct lyxml_elem *sub, *next;
2955 const char *value;
2956 int r;
2957 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002958 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002960 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002961 if (!anyxml) {
2962 LOGMEM;
2963 return NULL;
2964 }
Radek Krejci76512572015-08-04 09:47:08 +02002965 anyxml->nodetype = LYS_ANYXML;
2966 anyxml->prev = (struct lys_node *)anyxml;
2967 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002968
Michal Vaskoe0c59842015-09-24 13:52:20 +02002969 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2970 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 goto error;
2972 }
Radek Krejci863c2852015-06-03 15:47:11 +02002973
Radek Krejcia9544502015-08-14 08:24:29 +02002974 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002975
Michal Vasko4f0dad02016-02-15 14:08:23 +01002976 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002977 goto error;
2978 }
2979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002981 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2982 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002983 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002984 continue;
2985 }
2986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 if (!strcmp(sub->name, "mandatory")) {
2988 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002989 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 goto error;
2991 }
2992 /* just checking the flags in leaf is not sufficient, we would allow
2993 * multiple mandatory statements with the "false" value
2994 */
2995 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 GETVAL(value, sub, "value");
2998 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002999 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003000 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003001 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003002 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003003 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003004 goto error;
3005 }
3006 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003007 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003008 } else if (!strcmp(sub->name, "when")) {
3009 if (anyxml->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003010 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003011 goto error;
3012 }
3013
3014 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003015 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003016 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003017 goto error;
3018 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003019 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 } else if (!strcmp(sub->name, "must")) {
3021 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003022 } else if (!strcmp(sub->name, "if-feature")) {
3023 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003026 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003028 }
3029 }
Radek Krejci863c2852015-06-03 15:47:11 +02003030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 /* middle part - process nodes with cardinality of 0..n */
3032 if (c_must) {
3033 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003034 if (!anyxml->must) {
3035 LOGMEM;
3036 goto error;
3037 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003039 if (c_ftrs) {
3040 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003041 if (!anyxml->features) {
3042 LOGMEM;
3043 goto error;
3044 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003045 }
Radek Krejci863c2852015-06-03 15:47:11 +02003046
Radek Krejci73adb602015-07-02 18:07:40 +02003047 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003049 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3050 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 if (r) {
3052 goto error;
3053 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003054 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003055 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003056 anyxml->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003057 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003058 goto error;
3059 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 }
Radek Krejci863c2852015-06-03 15:47:11 +02003062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003064
3065error:
3066
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003067 lys_node_free(retval, NULL);
Radek Krejci863c2852015-06-03 15:47:11 +02003068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003070}
3071
Michal Vasko0d343d12015-08-24 14:57:36 +02003072/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003073static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003074read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003075 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003076{
Radek Krejci76512572015-08-04 09:47:08 +02003077 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003078 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003079 struct lyxml_elem *sub, *next;
3080 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003081 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003082 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003085 if (!leaf) {
3086 LOGMEM;
3087 return NULL;
3088 }
Radek Krejci76512572015-08-04 09:47:08 +02003089 leaf->nodetype = LYS_LEAF;
3090 leaf->prev = (struct lys_node *)leaf;
3091 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003092
Michal Vaskoe0c59842015-09-24 13:52:20 +02003093 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3094 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 goto error;
3096 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003097
Radek Krejcia9544502015-08-14 08:24:29 +02003098 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003099
Michal Vasko4f0dad02016-02-15 14:08:23 +01003100 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003101 goto error;
3102 }
3103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003105 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3106 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003107 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003108 continue;
3109 }
3110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003111 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003112 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003113 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003114 goto error;
3115 }
Michal Vasko88c29542015-11-27 14:57:53 +01003116 /* HACK for unres */
3117 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003118 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003119 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3120 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 goto error;
3122 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003123 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 } else if (!strcmp(sub->name, "default")) {
3125 if (leaf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01003126 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 goto error;
3128 }
3129 GETVAL(value, sub, "value");
3130 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003131 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 } else if (!strcmp(sub->name, "units")) {
3133 if (leaf->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01003134 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 goto error;
3136 }
3137 GETVAL(value, sub, "name");
3138 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3139 } else if (!strcmp(sub->name, "mandatory")) {
3140 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01003141 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 goto error;
3143 }
3144 /* just checking the flags in leaf is not sufficient, we would allow
3145 * multiple mandatory statements with the "false" value
3146 */
3147 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 GETVAL(value, sub, "value");
3150 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003151 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003152 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003153 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003154 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003155 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 goto error;
3157 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003158 } else if (!strcmp(sub->name, "when")) {
3159 if (leaf->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003160 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003161 goto error;
3162 }
3163
3164 leaf->when = read_yin_when(module, sub);
3165 if (!leaf->when) {
3166 goto error;
3167 }
3168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003170 c_must++;
3171 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003172 } else if (!strcmp(sub->name, "if-feature")) {
3173 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003174 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003177 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003180
Michal Vasko88c29542015-11-27 14:57:53 +01003181 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003184 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003185 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003186 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 goto error;
3188 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003189 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003190 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003191 goto error;
3192 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 /* middle part - process nodes with cardinality of 0..n */
3196 if (c_must) {
3197 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003198 if (!leaf->must) {
3199 LOGMEM;
3200 goto error;
3201 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003203 if (c_ftrs) {
3204 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003205 if (!leaf->features) {
3206 LOGMEM;
3207 goto error;
3208 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003209 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003210
Radek Krejci73adb602015-07-02 18:07:40 +02003211 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003213 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3214 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 if (r) {
3216 goto error;
3217 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003218 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003219 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003220 leaf->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003221 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003222 goto error;
3223 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003227 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003228
3229error:
3230
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003231 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003234}
3235
Michal Vasko0d343d12015-08-24 14:57:36 +02003236/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003237static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003238read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003239 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003240{
Radek Krejci76512572015-08-04 09:47:08 +02003241 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003242 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 struct lyxml_elem *sub, *next;
3244 const char *value;
3245 char *endptr;
3246 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003247 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003248 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003252 if (!llist) {
3253 LOGMEM;
3254 return NULL;
3255 }
Radek Krejci76512572015-08-04 09:47:08 +02003256 llist->nodetype = LYS_LEAFLIST;
3257 llist->prev = (struct lys_node *)llist;
3258 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003259
Michal Vaskoe0c59842015-09-24 13:52:20 +02003260 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3261 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 goto error;
3263 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003264
Radek Krejcia9544502015-08-14 08:24:29 +02003265 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003266
Michal Vasko4f0dad02016-02-15 14:08:23 +01003267 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003268 goto error;
3269 }
3270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003272 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3273 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003274 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003275 continue;
3276 }
3277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003279 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003280 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 goto error;
3282 }
Michal Vasko88c29542015-11-27 14:57:53 +01003283 /* HACK for unres */
3284 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003285 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003286 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3287 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 goto error;
3289 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003290 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 } else if (!strcmp(sub->name, "units")) {
3292 if (llist->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01003293 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 goto error;
3295 }
3296 GETVAL(value, sub, "name");
3297 llist->units = lydict_insert(module->ctx, value, strlen(value));
3298 } else if (!strcmp(sub->name, "ordered-by")) {
3299 if (f_ordr) {
Radek Krejciadb57612016-02-16 13:34:34 +01003300 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 goto error;
3302 }
3303 /* just checking the flags in llist is not sufficient, we would
3304 * allow multiple ordered-by statements with the "system" value
3305 */
3306 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003307
Radek Krejci1574a8d2015-08-03 14:16:52 +02003308 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3310 * state data
3311 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003312 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 continue;
3314 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 GETVAL(value, sub, "value");
3317 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003318 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 } else if (strcmp(value, "system")) {
Radek Krejciadb57612016-02-16 13:34:34 +01003320 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003322 } /* else system is the default value, so we can ignore it */
3323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 } else if (!strcmp(sub->name, "must")) {
3325 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003326 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003327 } else if (!strcmp(sub->name, "if-feature")) {
3328 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 } else if (!strcmp(sub->name, "min-elements")) {
3332 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01003333 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 goto error;
3335 }
3336 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 GETVAL(value, sub, "value");
3339 while (isspace(value[0])) {
3340 value++;
3341 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 /* convert it to uint32_t */
3344 errno = 0;
3345 endptr = NULL;
3346 val = strtoul(value, &endptr, 10);
3347 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003348 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 goto error;
3350 }
3351 llist->min = (uint32_t) val;
3352 } else if (!strcmp(sub->name, "max-elements")) {
3353 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003354 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 goto error;
3356 }
3357 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 GETVAL(value, sub, "value");
3360 while (isspace(value[0])) {
3361 value++;
3362 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003363
Radek Krejci0d7b2472016-02-12 11:11:03 +01003364 if (!strcmp(value, "unbounded")) {
3365 llist->max = 0;
3366 } else {
3367 /* convert it to uint32_t */
3368 errno = 0;
3369 endptr = NULL;
3370 val = strtoul(value, &endptr, 10);
3371 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003372 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003373 goto error;
3374 }
3375 llist->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003377 } else if (!strcmp(sub->name, "when")) {
3378 if (llist->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003379 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003380 goto error;
3381 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003382
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003383 llist->when = read_yin_when(module, sub);
3384 if (!llist->when) {
3385 goto error;
3386 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003388 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003389 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003391
Michal Vasko88c29542015-11-27 14:57:53 +01003392 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003396 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003397 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 goto error;
3399 }
3400 if (llist->max && llist->min > llist->max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003401 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003402 goto error;
3403 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 /* middle part - process nodes with cardinality of 0..n */
3406 if (c_must) {
3407 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003408 if (!llist->must) {
3409 LOGMEM;
3410 goto error;
3411 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003413 if (c_ftrs) {
3414 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003415 if (!llist->features) {
3416 LOGMEM;
3417 goto error;
3418 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003419 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003420
Radek Krejci73adb602015-07-02 18:07:40 +02003421 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003423 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3424 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 if (r) {
3426 goto error;
3427 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003428 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003429 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003430 llist->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003431 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003432 goto error;
3433 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003438
3439error:
3440
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003441 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003444}
3445
Michal Vasko0d343d12015-08-24 14:57:36 +02003446/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003447static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003448read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3449 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003450{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003451 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003452 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003454 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003455 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003457 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003458 char *auxs;
3459 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 /* init */
3462 memset(&root, 0, sizeof root);
3463 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003466 if (!list) {
3467 LOGMEM;
3468 return NULL;
3469 }
Radek Krejci76512572015-08-04 09:47:08 +02003470 list->nodetype = LYS_LIST;
3471 list->prev = (struct lys_node *)list;
3472 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003473
Michal Vaskoe0c59842015-09-24 13:52:20 +02003474 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3475 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 goto error;
3477 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003478
Radek Krejcia9544502015-08-14 08:24:29 +02003479 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 /* process list's specific children */
3482 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003483 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3484 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003485 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003486 continue;
3487 }
3488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 /* data statements */
3490 if (!strcmp(sub->name, "container") ||
3491 !strcmp(sub->name, "leaf-list") ||
3492 !strcmp(sub->name, "leaf") ||
3493 !strcmp(sub->name, "list") ||
3494 !strcmp(sub->name, "choice") ||
3495 !strcmp(sub->name, "uses") ||
3496 !strcmp(sub->name, "grouping") ||
3497 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003498 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003499 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 /* array counters */
3502 } else if (!strcmp(sub->name, "key")) {
3503 /* check cardinality 0..1 */
3504 if (list->keys_size) {
Radek Krejciadb57612016-02-16 13:34:34 +01003505 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 goto error;
3507 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 /* count the number of keys */
3510 GETVAL(value, sub, "value");
3511 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003512 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 while ((value = strpbrk(value, " \t\n"))) {
3514 list->keys_size++;
3515 while (isspace(*value)) {
3516 value++;
3517 }
3518 }
3519 list->keys_size++;
3520 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003521 if (!list->keys) {
3522 LOGMEM;
3523 goto error;
3524 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 } else if (!strcmp(sub->name, "unique")) {
3526 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003527 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003528 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 } else if (!strcmp(sub->name, "typedef")) {
3530 c_tpdf++;
3531 } else if (!strcmp(sub->name, "must")) {
3532 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003533 } else if (!strcmp(sub->name, "if-feature")) {
3534 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 /* optional stetments */
3537 } else if (!strcmp(sub->name, "ordered-by")) {
3538 if (f_ordr) {
Radek Krejciadb57612016-02-16 13:34:34 +01003539 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 goto error;
3541 }
3542 /* just checking the flags in llist is not sufficient, we would
3543 * allow multiple ordered-by statements with the "system" value
3544 */
3545 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003546
Radek Krejci1574a8d2015-08-03 14:16:52 +02003547 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003548 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3549 * state data
3550 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003551 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 continue;
3553 }
Radek Krejci345ad742015-06-03 11:04:18 +02003554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 GETVAL(value, sub, "value");
3556 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003557 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 } else if (strcmp(value, "system")) {
Radek Krejciadb57612016-02-16 13:34:34 +01003559 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 goto error;
3561 }
3562 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003563 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 } else if (!strcmp(sub->name, "min-elements")) {
3565 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01003566 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 goto error;
3568 }
3569 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 GETVAL(value, sub, "value");
3572 while (isspace(value[0])) {
3573 value++;
3574 }
Radek Krejci345ad742015-06-03 11:04:18 +02003575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003576 /* convert it to uint32_t */
3577 errno = 0;
3578 auxs = NULL;
3579 val = strtoul(value, &auxs, 10);
3580 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003581 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 goto error;
3583 }
3584 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003585 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 } else if (!strcmp(sub->name, "max-elements")) {
3587 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003588 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003589 goto error;
3590 }
3591 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 GETVAL(value, sub, "value");
3594 while (isspace(value[0])) {
3595 value++;
3596 }
Radek Krejci345ad742015-06-03 11:04:18 +02003597
Radek Krejci0d7b2472016-02-12 11:11:03 +01003598 if (!strcmp(value, "unbounded")) {
3599 list->max = 0;;
3600 } else {
3601 /* convert it to uint32_t */
3602 errno = 0;
3603 auxs = NULL;
3604 val = strtoul(value, &auxs, 10);
3605 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003606 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003607 goto error;
3608 }
3609 list->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003611 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003612 } else if (!strcmp(sub->name, "when")) {
3613 if (list->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003614 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003615 goto error;
3616 }
3617
3618 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003619 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003620 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003621 goto error;
3622 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003623 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003624 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003625 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003626 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 }
3628 }
Radek Krejci345ad742015-06-03 11:04:18 +02003629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003630 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003631 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejciadb57612016-02-16 13:34:34 +01003632 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 goto error;
3634 }
3635 if (list->max && list->min > list->max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003636 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 goto error;
3638 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3641 if (c_tpdf) {
3642 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003643 if (!list->tpdf) {
3644 LOGMEM;
3645 goto error;
3646 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003648 if (c_must) {
3649 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003650 if (!list->must) {
3651 LOGMEM;
3652 goto error;
3653 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003654 }
3655 if (c_ftrs) {
3656 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003657 if (!list->features) {
3658 LOGMEM;
3659 goto error;
3660 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003661 }
Radek Krejci73adb602015-07-02 18:07:40 +02003662 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003664 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3665 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 if (r) {
3667 goto error;
3668 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003669 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003670 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003671 list->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003672 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003673 goto error;
3674 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003675 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003676 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3677 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003678 if (r) {
3679 goto error;
3680 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003681 }
3682 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003683
Michal Vasko4f0dad02016-02-15 14:08:23 +01003684 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003685 goto error;
3686 }
3687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 /* last part - process data nodes */
3689 LY_TREE_FOR_SAFE(root.child, next, sub) {
3690 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003691 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003692 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003693 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003695 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003697 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003699 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003701 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003703 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003705 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003706 } else {
3707 LOGINT;
3708 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003710 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 goto error;
3712 }
Radek Krejci73adb602015-07-02 18:07:40 +02003713
Michal Vasko345da0a2015-12-02 10:35:55 +01003714 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003716
Radek Krejci461efb92016-02-12 15:52:18 +01003717 if (key_str) {
3718 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
3719 goto error;
3720 }
3721 } /* 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 +02003722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003723 /* process unique statements */
3724 if (c_uniq) {
3725 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003726 if (!list->unique) {
3727 LOGMEM;
3728 goto error;
3729 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003730
Radek Krejci461efb92016-02-12 15:52:18 +01003731 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3732 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3733 list->unique_size++;
3734 if (r) {
3735 goto error;
3736 }
3737
3738 lyxml_free(module->ctx, sub);
3739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003743
3744error:
3745
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003746 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003747 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003748 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 }
3750 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003751 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755}
3756
Michal Vasko0d343d12015-08-24 14:57:36 +02003757/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003758static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003759read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3760 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003763 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003764 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003765 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 const char *value;
3767 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003768 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 /* init */
3771 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003774 if (!cont) {
3775 LOGMEM;
3776 return NULL;
3777 }
Radek Krejci76512572015-08-04 09:47:08 +02003778 cont->nodetype = LYS_CONTAINER;
3779 cont->prev = (struct lys_node *)cont;
3780 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003781
Michal Vaskoe0c59842015-09-24 13:52:20 +02003782 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3783 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 goto error;
3785 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003786
Radek Krejcia9544502015-08-14 08:24:29 +02003787 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 /* process container's specific children */
3790 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003791 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003792 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003793 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003794 continue;
3795 }
3796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 if (!strcmp(sub->name, "presence")) {
3798 if (cont->presence) {
Radek Krejciadb57612016-02-16 13:34:34 +01003799 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 goto error;
3801 }
3802 GETVAL(value, sub, "value");
3803 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003804
Michal Vasko345da0a2015-12-02 10:35:55 +01003805 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003806 } else if (!strcmp(sub->name, "when")) {
3807 if (cont->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003808 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003809 goto error;
3810 }
3811
3812 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003813 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003814 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003815 goto error;
3816 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003817 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 /* data statements */
3820 } else if (!strcmp(sub->name, "container") ||
3821 !strcmp(sub->name, "leaf-list") ||
3822 !strcmp(sub->name, "leaf") ||
3823 !strcmp(sub->name, "list") ||
3824 !strcmp(sub->name, "choice") ||
3825 !strcmp(sub->name, "uses") ||
3826 !strcmp(sub->name, "grouping") ||
3827 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003828 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003829 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 /* array counters */
3832 } else if (!strcmp(sub->name, "typedef")) {
3833 c_tpdf++;
3834 } else if (!strcmp(sub->name, "must")) {
3835 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003836 } else if (!strcmp(sub->name, "if-feature")) {
3837 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003839 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 }
3842 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3845 if (c_tpdf) {
3846 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003847 if (!cont->tpdf) {
3848 LOGMEM;
3849 goto error;
3850 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 }
3852 if (c_must) {
3853 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003854 if (!cont->must) {
3855 LOGMEM;
3856 goto error;
3857 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003859 if (c_ftrs) {
3860 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003861 if (!cont->features) {
3862 LOGMEM;
3863 goto error;
3864 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003865 }
Radek Krejci800af702015-06-02 13:46:01 +02003866
Radek Krejci73adb602015-07-02 18:07:40 +02003867 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003869 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3870 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 if (r) {
3872 goto error;
3873 }
3874 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003875 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3876 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 if (r) {
3878 goto error;
3879 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003880 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01003881 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003882 cont->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003883 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003884 goto error;
3885 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003888
Michal Vasko4f0dad02016-02-15 14:08:23 +01003889 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003890 goto error;
3891 }
3892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 /* last part - process data nodes */
3894 LY_TREE_FOR_SAFE(root.child, next, sub) {
3895 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003896 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003898 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003900 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003902 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003903 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003904 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003906 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003908 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003909 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003910 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003912 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 goto error;
3914 }
Radek Krejci73adb602015-07-02 18:07:40 +02003915
Michal Vasko345da0a2015-12-02 10:35:55 +01003916 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003920
3921error:
3922
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003923 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003925 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003929}
3930
Michal Vasko0d343d12015-08-24 14:57:36 +02003931/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003932static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003933read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003934 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003935{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003937 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003938 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003939 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003940 int r;
3941 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 /* init */
3944 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003947 if (!grp) {
3948 LOGMEM;
3949 return NULL;
3950 }
Radek Krejci76512572015-08-04 09:47:08 +02003951 grp->nodetype = LYS_GROUPING;
3952 grp->prev = (struct lys_node *)grp;
3953 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003954
Michal Vasko71e1aa82015-08-12 12:17:51 +02003955 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003956 goto error;
3957 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003958
Radek Krejcia9544502015-08-14 08:24:29 +02003959 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3960
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003962 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3963 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003964 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003965 continue;
3966 }
3967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 /* data statements */
3969 if (!strcmp(sub->name, "container") ||
3970 !strcmp(sub->name, "leaf-list") ||
3971 !strcmp(sub->name, "leaf") ||
3972 !strcmp(sub->name, "list") ||
3973 !strcmp(sub->name, "choice") ||
3974 !strcmp(sub->name, "uses") ||
3975 !strcmp(sub->name, "grouping") ||
3976 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003977 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003978 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980 /* array counters */
3981 } else if (!strcmp(sub->name, "typedef")) {
3982 c_tpdf++;
3983 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003984 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 goto error;
3986 }
3987 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3990 if (c_tpdf) {
3991 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003992 if (!grp->tpdf) {
3993 LOGMEM;
3994 goto error;
3995 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003997 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003998 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3999 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004000 if (r) {
4001 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004002 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004004
Michal Vasko4f0dad02016-02-15 14:08:23 +01004005 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004006 goto error;
4007 }
4008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 /* last part - process data nodes */
4010 LY_TREE_FOR_SAFE(root.child, next, sub) {
4011 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004012 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004013 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004014 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004016 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004018 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004019 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004020 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004022 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004024 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004025 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004026 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004028 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004029 goto error;
4030 }
Radek Krejci73adb602015-07-02 18:07:40 +02004031
Michal Vasko345da0a2015-12-02 10:35:55 +01004032 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004036
4037error:
4038
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004039 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004040 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004041 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004042 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004044 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004045}
4046
Michal Vasko0d343d12015-08-24 14:57:36 +02004047/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004048static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004049read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4050 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004051{
Radek Krejcie0674f82015-06-15 13:58:51 +02004052 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004053 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004054 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004055 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004056 int r;
4057 int c_tpdf = 0;
4058
Radek Krejcie0674f82015-06-15 13:58:51 +02004059 /* init */
4060 memset(&root, 0, sizeof root);
4061
Michal Vasko38d01f72015-06-15 09:41:06 +02004062 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004063 if (!inout) {
4064 LOGMEM;
4065 return NULL;
4066 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004067 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004068
4069 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004070 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004071 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004072 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004073 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004074 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004075 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004076 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004077 }
4078
Radek Krejci76512572015-08-04 09:47:08 +02004079 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004080
Radek Krejci6a113852015-07-03 16:04:20 +02004081 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004082 goto error;
4083 }
4084
Radek Krejcia9544502015-08-14 08:24:29 +02004085 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4086
Michal Vasko38d01f72015-06-15 09:41:06 +02004087 /* data statements */
4088 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004089 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4090 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004091 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004092 continue;
4093 }
4094
Michal Vasko38d01f72015-06-15 09:41:06 +02004095 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004096 !strcmp(sub->name, "leaf-list") ||
4097 !strcmp(sub->name, "leaf") ||
4098 !strcmp(sub->name, "list") ||
4099 !strcmp(sub->name, "choice") ||
4100 !strcmp(sub->name, "uses") ||
4101 !strcmp(sub->name, "grouping") ||
4102 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004103 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004104 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004107 } else if (!strcmp(sub->name, "typedef")) {
4108 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004109
Michal Vasko38d01f72015-06-15 09:41:06 +02004110 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004111 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004112 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004113 }
4114 }
4115
4116 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4117 if (c_tpdf) {
4118 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004119 if (!inout->tpdf) {
4120 LOGMEM;
4121 goto error;
4122 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004123 }
4124
Radek Krejci73adb602015-07-02 18:07:40 +02004125 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004126 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4127 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004128 if (r) {
4129 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004130 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 }
4132
Michal Vasko4f0dad02016-02-15 14:08:23 +01004133 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004134 goto error;
4135 }
4136
Michal Vasko38d01f72015-06-15 09:41:06 +02004137 /* last part - process data nodes */
4138 LY_TREE_FOR_SAFE(root.child, next, sub) {
4139 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004140 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004141 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004142 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004143 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004144 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004145 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004146 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004147 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004148 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004149 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004150 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004151 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004152 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004153 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004154 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004156 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004157 goto error;
4158 }
Radek Krejci73adb602015-07-02 18:07:40 +02004159
Michal Vasko345da0a2015-12-02 10:35:55 +01004160 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004161 }
4162
Michal Vasko38d01f72015-06-15 09:41:06 +02004163 return retval;
4164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004165error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004166
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004167 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004168 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004169 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 }
4171
4172 return NULL;
4173}
4174
Michal Vasko0d343d12015-08-24 14:57:36 +02004175/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004176static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004177read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4178 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004179{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004180 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004181 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004182 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004183 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004184 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004185 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004186
Michal Vaskoc6551b32015-06-16 10:51:43 +02004187 memset(&root, 0, sizeof root);
4188
Michal Vasko0ea41032015-06-16 08:53:55 +02004189 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004190 if (!notif) {
4191 LOGMEM;
4192 return NULL;
4193 }
Radek Krejci76512572015-08-04 09:47:08 +02004194 notif->nodetype = LYS_NOTIF;
4195 notif->prev = (struct lys_node *)notif;
4196 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004197
Radek Krejci6a113852015-07-03 16:04:20 +02004198 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004199 goto error;
4200 }
4201
Radek Krejcia9544502015-08-14 08:24:29 +02004202 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4203
Michal Vasko0ea41032015-06-16 08:53:55 +02004204 /* process rpc's specific children */
4205 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004206 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4207 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004208 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004209 continue;
4210 }
4211
Michal Vasko0ea41032015-06-16 08:53:55 +02004212 /* data statements */
4213 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 !strcmp(sub->name, "leaf-list") ||
4215 !strcmp(sub->name, "leaf") ||
4216 !strcmp(sub->name, "list") ||
4217 !strcmp(sub->name, "choice") ||
4218 !strcmp(sub->name, "uses") ||
4219 !strcmp(sub->name, "grouping") ||
4220 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004221 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004222 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004224 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004225 } else if (!strcmp(sub->name, "typedef")) {
4226 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004227 } else if (!strcmp(sub->name, "if-feature")) {
4228 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004229 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004230 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004231 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004232 }
4233 }
4234
4235 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4236 if (c_tpdf) {
4237 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004238 if (!notif->tpdf) {
4239 LOGMEM;
4240 goto error;
4241 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004243 if (c_ftrs) {
4244 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004245 if (!notif->features) {
4246 LOGMEM;
4247 goto error;
4248 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004249 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004250
Radek Krejci73adb602015-07-02 18:07:40 +02004251 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004252 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004253 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4254 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004255 if (r) {
4256 goto error;
4257 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004258 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004259 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004260 notif->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004261 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004262 goto error;
4263 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004264 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 }
4266
Michal Vasko4f0dad02016-02-15 14:08:23 +01004267 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004268 goto error;
4269 }
4270
Michal Vasko0ea41032015-06-16 08:53:55 +02004271 /* last part - process data nodes */
4272 LY_TREE_FOR_SAFE(root.child, next, sub) {
4273 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004274 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004275 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004276 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004277 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004278 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004279 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004280 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004281 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004282 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004283 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004284 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004285 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004286 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004287 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004288 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004289 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004290 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004291 goto error;
4292 }
Radek Krejci73adb602015-07-02 18:07:40 +02004293
Michal Vasko345da0a2015-12-02 10:35:55 +01004294 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004295 }
4296
Michal Vasko0ea41032015-06-16 08:53:55 +02004297 return retval;
4298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004300
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004301 lys_node_free(retval, NULL);
Michal Vasko0ea41032015-06-16 08:53:55 +02004302 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004303 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004304 }
4305
4306 return NULL;
4307}
4308
Michal Vasko0d343d12015-08-24 14:57:36 +02004309/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004310static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004311read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4312 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004313{
Radek Krejcie0674f82015-06-15 13:58:51 +02004314 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004315 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004316 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004317 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004318 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004319 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004320
Radek Krejcie0674f82015-06-15 13:58:51 +02004321 /* init */
4322 memset(&root, 0, sizeof root);
4323
Michal Vasko38d01f72015-06-15 09:41:06 +02004324 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004325 if (!rpc) {
4326 LOGMEM;
4327 return NULL;
4328 }
Radek Krejci76512572015-08-04 09:47:08 +02004329 rpc->nodetype = LYS_RPC;
4330 rpc->prev = (struct lys_node *)rpc;
4331 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004332
Radek Krejci6a113852015-07-03 16:04:20 +02004333 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004334 goto error;
4335 }
4336
Radek Krejcia9544502015-08-14 08:24:29 +02004337 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4338
Michal Vasko38d01f72015-06-15 09:41:06 +02004339 /* process rpc's specific children */
4340 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004341 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4342 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004343 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004344 continue;
4345 }
4346
Michal Vasko38d01f72015-06-15 09:41:06 +02004347 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004349 && (rpc->child->nodetype == LYS_INPUT
4350 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004351 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004352 goto error;
4353 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004354 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004355 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004356 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004358 && (rpc->child->nodetype == LYS_INPUT
4359 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004360 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004361 goto error;
4362 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004363 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004364 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004367 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004368 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004369 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004372 } else if (!strcmp(sub->name, "typedef")) {
4373 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004374 } else if (!strcmp(sub->name, "if-feature")) {
4375 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004376 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004377 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004378 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004379 }
4380 }
4381
4382 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4383 if (c_tpdf) {
4384 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004385 if (!rpc->tpdf) {
4386 LOGMEM;
4387 goto error;
4388 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004389 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004390 if (c_ftrs) {
4391 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004392 if (!rpc->features) {
4393 LOGMEM;
4394 goto error;
4395 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004396 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004397
Radek Krejci73adb602015-07-02 18:07:40 +02004398 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004399 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004400 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4401 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004402 if (r) {
4403 goto error;
4404 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004405 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004406 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004407 rpc->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004408 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004409 goto error;
4410 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004411 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004412 }
4413
Michal Vasko4f0dad02016-02-15 14:08:23 +01004414 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004415 goto error;
4416 }
4417
Michal Vasko38d01f72015-06-15 09:41:06 +02004418 /* last part - process data nodes */
4419 LY_TREE_FOR_SAFE(root.child, next, sub) {
4420 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004421 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004422 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004423 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004424 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004425 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004426 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004427 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004428 goto error;
4429 }
Radek Krejci73adb602015-07-02 18:07:40 +02004430
Michal Vasko345da0a2015-12-02 10:35:55 +01004431 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004432 }
4433
Michal Vasko38d01f72015-06-15 09:41:06 +02004434 return retval;
4435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004437
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004438 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004439 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004440 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004441 }
4442
4443 return NULL;
4444}
4445
Michal Vasko0d343d12015-08-24 14:57:36 +02004446/* logs directly
4447 *
Radek Krejci74705112015-06-05 10:25:44 +02004448 * resolve - referenced grouping should be bounded to the namespace (resolved)
4449 * only when uses does not appear in grouping. In a case of grouping's uses,
4450 * we just get information but we do not apply augment or refine to it.
4451 */
Radek Krejci76512572015-08-04 09:47:08 +02004452static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004453read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004454 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004455{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004456 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004457 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004458 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004460 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004464 if (!uses) {
4465 LOGMEM;
4466 return NULL;
4467 }
Radek Krejci76512572015-08-04 09:47:08 +02004468 uses->nodetype = LYS_USES;
4469 uses->prev = (struct lys_node *)uses;
4470 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004471
Radek Krejcia9544502015-08-14 08:24:29 +02004472 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004474
Michal Vaskoe0c59842015-09-24 13:52:20 +02004475 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4476 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004477 goto error;
4478 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004479
Radek Krejcia9544502015-08-14 08:24:29 +02004480 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004482 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004483 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004484 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4485 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004486 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004487 continue;
4488 }
4489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004490 if (!strcmp(sub->name, "refine")) {
4491 c_ref++;
4492 } else if (!strcmp(sub->name, "augment")) {
4493 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004494 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004495 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004496 } else if (!strcmp(sub->name, "when")) {
4497 if (uses->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01004498 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004499 goto error;
4500 }
4501
4502 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004503 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004504 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004505 goto error;
4506 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004507 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004508 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004509 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 }
4512 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 /* process properties with cardinality 0..n */
4515 if (c_ref) {
4516 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004517 if (!uses->refine) {
4518 LOGMEM;
4519 goto error;
4520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 }
4522 if (c_aug) {
4523 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004524 if (!uses->augment) {
4525 LOGMEM;
4526 goto error;
4527 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004529 if (c_ftrs) {
4530 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004531 if (!uses->features) {
4532 LOGMEM;
4533 goto error;
4534 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004535 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004536
Michal Vasko4f0dad02016-02-15 14:08:23 +01004537 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004538 goto error;
4539 }
4540
Radek Krejcia9544502015-08-14 08:24:29 +02004541 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004543 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4544 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004545 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004546 goto error;
4547 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004548 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004549 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4550 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004551 if (r) {
4552 goto error;
4553 }
4554 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko1d337e12016-02-15 12:32:04 +01004555 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004556 uses->features_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004557 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004558 goto error;
4559 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 }
4561 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004562
Michal Vasko0bd29d12015-08-19 11:45:49 +02004563 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004564 goto error;
4565 }
Radek Krejci74705112015-06-05 10:25:44 +02004566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 if (resolve) {
4568 /* inherit config flag */
4569 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004570 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 } else {
4572 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004573 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 }
4575 }
Radek Krejcib388c152015-06-04 17:03:03 +02004576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004578
4579error:
4580
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004581 lys_node_free(retval, NULL);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004582
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004583 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004584}
4585
Michal Vasko0d343d12015-08-24 14:57:36 +02004586/* logs directly
4587 *
4588 * common code for yin_read_module() and yin_read_submodule()
4589 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590static int
Radek Krejcic071c542016-01-27 14:57:51 +01004591read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4592 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004593{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004595 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004596 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004597 struct lys_module *trg;
4598 struct lys_import *aux_imp;
4599 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004601 int i, j, r;
4602 int inc_size_aux = 0;
4603 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004604 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004605 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 +02004606
Radek Krejcic071c542016-01-27 14:57:51 +01004607 /* to simplify code, store the module/submodule being processed as trg */
4608 trg = submodule ? (struct lys_module*)submodule : module;
4609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 /* init */
4611 memset(&root, 0, sizeof root);
4612 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004613 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 /*
4616 * in the first run, we process elements with cardinality of 1 or 0..1 and
4617 * count elements with cardinality 0..n. Data elements (choices, containers,
4618 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4619 * need have all top-level and groupings already prepared at that time. In
4620 * the middle loop, we process other elements with carinality of 0..n since
4621 * we need to allocate arrays to store them.
4622 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004623 LY_TREE_FOR_SAFE(yin->child, next, child) {
4624 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004625 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004626 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004627 continue;
4628 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004629
Radek Krejcic071c542016-01-27 14:57:51 +01004630 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 if (module->ns) {
Radek Krejciadb57612016-02-16 13:34:34 +01004632 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 goto error;
4634 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004635 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004637 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004638 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004639 if (module->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004640 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 goto error;
4642 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004643 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004644 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004645 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 goto error;
4647 }
4648 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004649 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004650 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4651 if (submodule->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004652 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 goto error;
4654 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004655 GETVAL(value, child, "module");
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01004656 if (!ly_strequal(value, submodule->belongsto->name)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004657 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 goto error;
4659 }
Radek Krejcif3886932015-06-04 17:36:06 +02004660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004662 if (!child->child) {
Radek Krejciadb57612016-02-16 13:34:34 +01004663 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), LY_VLOG_XML, child, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004665 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejciadb57612016-02-16 13:34:34 +01004666 LOGVAL(LYE_INSTMT, LOGLINE(child->child), LY_VLOG_XML, child->child, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004668 } else if (child->child->next) {
Radek Krejciadb57612016-02-16 13:34:34 +01004669 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), LY_VLOG_XML, child->child->next,
4670 child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 goto error;
4672 }
4673 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004674 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004675 /* check here differs from a generic prefix check, since this prefix
4676 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004677 */
Radek Krejcic6556022016-01-27 15:16:45 +01004678 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004679 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child->child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004680 goto error;
4681 }
Radek Krejcic071c542016-01-27 14:57:51 +01004682 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004685 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004686
4687 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004688 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004692 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004693 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004694 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004696 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004698 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004699 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004700 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004701 lyxml_unlink_elem(ctx, child, 2);
4702 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004703
Radek Krejci1d82ef62015-08-07 14:44:40 +02004704 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004705 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004706 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004707 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004710 } else if (!strcmp(child->name, "container") ||
4711 !strcmp(child->name, "leaf-list") ||
4712 !strcmp(child->name, "leaf") ||
4713 !strcmp(child->name, "list") ||
4714 !strcmp(child->name, "choice") ||
4715 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004716 !strcmp(child->name, "anyxml") ||
4717 !strcmp(child->name, "rpc") ||
4718 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004719 lyxml_unlink_elem(ctx, child, 2);
4720 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004721
Radek Krejci1d82ef62015-08-07 14:44:40 +02004722 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004723 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004724 lyxml_unlink_elem(ctx, child, 2);
4725 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004728 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004729 if (trg->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01004730 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 goto error;
4732 }
Radek Krejcic071c542016-01-27 14:57:51 +01004733 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004734 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004735 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 goto error;
4737 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004738 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004739 if (trg->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01004740 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 goto error;
4742 }
Radek Krejcic071c542016-01-27 14:57:51 +01004743 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004744 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004745 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 goto error;
4747 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004748 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004749 if (trg->org) {
Radek Krejciadb57612016-02-16 13:34:34 +01004750 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 goto error;
4752 }
Radek Krejcic071c542016-01-27 14:57:51 +01004753 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004754 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004755 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 goto error;
4757 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004758 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004759 if (trg->contact) {
Radek Krejciadb57612016-02-16 13:34:34 +01004760 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 goto error;
4762 }
Radek Krejcic071c542016-01-27 14:57:51 +01004763 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004764 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004765 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 goto error;
4767 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004768 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004769 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004770 if (version_flag) {
Radek Krejciadb57612016-02-16 13:34:34 +01004771 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004772 goto error;
4773 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 if (strcmp(value, "1")) {
Radek Krejciadb57612016-02-16 13:34:34 +01004776 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 goto error;
4778 }
Radek Krejcic071c542016-01-27 14:57:51 +01004779 version_flag = 1;
4780 if (!submodule) {
4781 module->version = 1;
4782 } /* 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 +01004783 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004784
Radek Krejci1d82ef62015-08-07 14:44:40 +02004785 } else if (!strcmp(child->name, "extension")) {
4786 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004787
Radek Krejci3d468122015-10-02 13:36:12 +02004788 /* we have the following supported (hardcoded) extensions: */
4789 /* ietf-netconf's get-filter-element-attributes */
4790 if (!strcmp(module->ns, LY_NSNC) &&
4791 !strcmp(value, "get-filter-element-attributes")) {
4792 LOGDBG("NETCONF filter extension found");
4793 /* NACM's default-deny-write and default-deny-all */
4794 } else if (!strcmp(module->ns, LY_NSNACM) &&
4795 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4796 LOGDBG("NACM extension found");
4797 /* other extensions are not supported, so inform about such an extension */
4798 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004799 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004800 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004801 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004803 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004805 }
4806 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004807
Radek Krejcic071c542016-01-27 14:57:51 +01004808 /* check for mandatory statements */
4809 if (submodule && !submodule->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004810 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004811 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004812 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 if (!module->ns) {
Radek Krejciadb57612016-02-16 13:34:34 +01004814 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 goto error;
4816 }
4817 if (!module->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004818 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004819 goto error;
4820 }
4821 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004822
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004823 /* allocate arrays for elements with cardinality of 0..n */
4824 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004825 trg->imp = calloc(c_imp, sizeof *trg->imp);
4826 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004827 LOGMEM;
4828 goto error;
4829 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 }
4831 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004832 trg->rev = calloc(c_rev, sizeof *trg->rev);
4833 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004834 LOGMEM;
4835 goto error;
4836 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837 }
4838 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004839 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4840 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004841 LOGMEM;
4842 goto error;
4843 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 }
4845 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004846 trg->ident = calloc(c_ident, sizeof *trg->ident);
4847 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004848 LOGMEM;
4849 goto error;
4850 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 }
4852 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004853 trg->inc = calloc(c_inc, sizeof *trg->inc);
4854 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004855 LOGMEM;
4856 goto error;
4857 }
Radek Krejcic071c542016-01-27 14:57:51 +01004858 trg->inc_size = c_inc;
4859 /* trg->inc_size can be updated by the included submodules,
4860 * so we will use inc_size_aux here, trg->inc_size stores the
4861 * target size of the array
4862 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004864 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004865 trg->augment = calloc(c_aug, sizeof *trg->augment);
4866 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004867 LOGMEM;
4868 goto error;
4869 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004870 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004871 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004872 trg->features = calloc(c_ftrs, sizeof *trg->features);
4873 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004874 LOGMEM;
4875 goto error;
4876 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004877 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004878 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004879 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4880 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004881 LOGMEM;
4882 goto error;
4883 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004884 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004885
Michal Vasko2f7925f2015-10-21 15:06:56 +02004886 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4887 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004888 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004889 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4890 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 if (r) {
4892 goto error;
4893 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004895 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004896 for (i = 0; i < trg->imp_size - 1; i++) {
4897 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004898 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004899 goto error;
4900 }
4901 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004902
Radek Krejci1d82ef62015-08-07 14:44:40 +02004903 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004904 memset(&inc, 0, sizeof inc);
4905 /* 1) pass module, not trg, since we want to pass the main module
4906 * 2) we cannot pass directly the structure in the array since
4907 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004908 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004909 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4910 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004911 if (r) {
4912 goto error;
4913 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004916 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004917 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004918 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child, "Including submodule \"%s\" repeatedly.",
Michal Vasko27ab8222016-02-12 09:33:52 +01004919 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 goto error;
4921 }
4922 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004923
Radek Krejci1d82ef62015-08-07 14:44:40 +02004924 } else if (!strcmp(child->name, "revision")) {
4925 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004926 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004927 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 goto error;
4929 }
Radek Krejcic071c542016-01-27 14:57:51 +01004930 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004931 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004932 for (i = 0; i < trg->rev_size; i++) {
4933 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004934 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
4935 LOGVAL(LYE_SPEC, 0, 0, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 }
4937 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004938
Radek Krejci1d82ef62015-08-07 14:44:40 +02004939 LY_TREE_FOR(child->child, child2) {
4940 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004941 if (trg->rev[trg->rev_size].dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01004942 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004943 goto error;
4944 }
Radek Krejcic071c542016-01-27 14:57:51 +01004945 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4946 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 goto error;
4948 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004949 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004950 if (trg->rev[trg->rev_size].ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01004951 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 goto error;
4953 }
Radek Krejcic071c542016-01-27 14:57:51 +01004954 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4955 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 goto error;
4957 }
4958 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004959 LOGVAL(LYE_INSTMT, LOGLINE(child2), LY_VLOG_XML, child2, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004960 goto error;
4961 }
4962 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004965 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004967 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004968 if (!value) {
4969 LOGMEM;
4970 goto error;
4971 }
Radek Krejcic071c542016-01-27 14:57:51 +01004972 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4973 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004975
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01004976 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004977 value = trg->rev[0].dsc;
4978 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4979 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004980 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004981
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01004982 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004983 value = trg->rev[0].ref;
4984 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4985 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 }
4987 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004988
Radek Krejcic071c542016-01-27 14:57:51 +01004989 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004990
Radek Krejci1d82ef62015-08-07 14:44:40 +02004991 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004992 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4993 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004994 if (r) {
4995 goto error;
4996 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004997
Radek Krejci1d82ef62015-08-07 14:44:40 +02004998 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004999 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5000 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 if (r) {
5002 goto error;
5003 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005004
Radek Krejci1d82ef62015-08-07 14:44:40 +02005005 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005006 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5007 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005008 if (r) {
5009 goto error;
5010 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005011
Radek Krejci1d82ef62015-08-07 14:44:40 +02005012 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005013 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5014 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005015 if (r) {
5016 goto error;
5017 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005018 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5019 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005022 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005023
Radek Krejcic071c542016-01-27 14:57:51 +01005024 if (submodule) {
5025 /* propagate imports into the main module */
5026 for (i = r = 0; i < submodule->imp_size; i++) {
5027 for (j = 0; j < module->imp_size; j++) {
5028 if (submodule->imp[i].module == module->imp[j].module &&
5029 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5030 /* check prefix match */
Radek Krejcic1ffa4d2016-02-17 13:11:11 +01005031 if (!ly_strequal(submodule->imp[i].prefix, module->imp[j].prefix)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005032 LOGVAL(LYE_INID, LOGLINE(yin), LY_VLOG_XML, yin, submodule->imp[i].prefix,
Radek Krejcic071c542016-01-27 14:57:51 +01005033 "non-matching prefixes of imported module in main module and submodule");
5034 goto error;
5035 }
5036 break;
5037 }
5038 }
5039 if (j == module->imp_size) {
5040 /* new import */
5041 r++;
5042 }
5043 }
5044 if (r) {
5045 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5046 if (!aux_imp) {
5047 LOGMEM;
5048 goto error;
5049 }
5050 module->imp = aux_imp;
5051 for (i = r = 0; i < submodule->imp_size; i++) {
5052 for (j = 0; j < module->imp_size; j++) {
5053 if (submodule->imp[i].module == module->imp[j].module) {
5054 break;
5055 }
5056 }
5057 if (j == module->imp_size) {
5058 /* new import */
5059 /* check prefix uniqueness */
5060 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005061 LOGVAL(LYE_DUPID, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", submodule->imp[i].prefix);
Radek Krejcic071c542016-01-27 14:57:51 +01005062 goto error;
5063 }
5064 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5065 module->imp[module->imp_size + r].external = 1;
5066 r++;
5067 }
5068 }
5069 module->imp_size += r;
5070 }
5071
Michal Vaskoe2905632016-02-11 15:42:24 +01005072 /* propagate includes into the main module */
Radek Krejcic071c542016-01-27 14:57:51 +01005073 for (i = r = 0; i < submodule->inc_size; i++) {
5074 for (j = 0; j < module->inc_size; j++) {
5075 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5076 break;
5077 }
5078 }
5079 if (j == module->inc_size) {
5080 /* new include */
5081 r++;
5082 }
5083 }
5084
5085 if (r) {
5086 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5087 if (!aux_inc) {
5088 LOGMEM;
5089 goto error;
5090 }
5091 module->inc = aux_inc;
5092 for (i = r = 0; i < submodule->inc_size; i++) {
5093 for (j = 0; j < module->inc_size; j++) {
5094 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5095 break;
5096 }
5097 }
5098 if (j == module->inc_size) {
5099 /* new include */
5100 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5101 module->inc[module->inc_size + r].external = 1;
5102 r++;
5103 }
5104 }
5105 module->inc_size += r;
5106 }
5107 }
5108
Radek Krejcif5be10f2015-06-16 13:29:36 +02005109 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005110 * refer to them. Submodule's data nodes are stored in the
5111 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005112 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005113 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005114 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005115 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 goto error;
5117 }
Radek Krejci74705112015-06-05 10:25:44 +02005118
Michal Vasko345da0a2015-12-02 10:35:55 +01005119 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005120 }
Radek Krejci74705112015-06-05 10:25:44 +02005121
Radek Krejcif5be10f2015-06-16 13:29:36 +02005122 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005123 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005124
Radek Krejci1d82ef62015-08-07 14:44:40 +02005125 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005126 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005127 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005128 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005129 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005130 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005131 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005132 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005133 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005134 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005135 } else if (!strcmp(child->name, "uses")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005136 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005137 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005138 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005139 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005140 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005141 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005142 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005143 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005144 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005145 goto error;
5146 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005147
Michal Vasko345da0a2015-12-02 10:35:55 +01005148 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005149 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005150
Michal Vasko2f7925f2015-10-21 15:06:56 +02005151 /* ... and finally augments (last, so we can augment our data, for instance) */
5152 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005153 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5154 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005155
Michal Vasko2f7925f2015-10-21 15:06:56 +02005156 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005157 goto error;
5158 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005159 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005160 }
5161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005162 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005163
5164error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005165 /* cleanup */
5166 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005167 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005168 }
5169 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005170 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005172 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005173 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005174 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005177}
5178
Michal Vasko0d343d12015-08-24 14:57:36 +02005179/* logs directly */
Michal Vasko2e7241e2016-02-15 16:06:34 +01005180int
5181yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres, struct lys_submodule **submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02005182{
Michal Vasko9f258e42016-02-11 11:36:27 +01005183 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005184 struct lyxml_elem *yin;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005186 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005187
Michal Vasko2e7241e2016-02-15 16:06:34 +01005188 assert(module->ctx && data && submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02005189
Radek Krejci722b0072016-02-01 17:09:45 +01005190 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005191 if (!yin) {
Michal Vasko2e7241e2016-02-15 16:06:34 +01005192 return -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005195 /* check root element */
5196 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejciadb57612016-02-16 13:34:34 +01005197 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005198 goto error;
5199 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005201 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005202 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005203 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 goto error;
5205 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005206
Michal Vasko2e7241e2016-02-15 16:06:34 +01005207 *submodule = calloc(1, sizeof **submodule);
5208 if (!(*submodule)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005209 LOGMEM;
5210 goto error;
5211 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005212
Michal Vasko2e7241e2016-02-15 16:06:34 +01005213 (*submodule)->ctx = module->ctx;
5214 (*submodule)->name = lydict_insert(module->ctx, value, strlen(value));
5215 (*submodule)->type = 1;
5216 (*submodule)->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005217
Michal Vasko2e7241e2016-02-15 16:06:34 +01005218 LOGVRB("Reading submodule \"%s\".", (*submodule)->name);
5219 if (read_sub_module(module, *submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 goto error;
5221 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005224 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005225
Michal Vasko2e7241e2016-02-15 16:06:34 +01005226 LOGVRB("Submodule \"%s\" successfully parsed.", (*submodule)->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005227
Michal Vasko2e7241e2016-02-15 16:06:34 +01005228 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005229
5230error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005231 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005232 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005233
Michal Vasko2e7241e2016-02-15 16:06:34 +01005234 if (!(*submodule)) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005235 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01005236 return -1;
Radek Krejcidaea8212016-02-15 08:28:20 +01005237 }
5238
Michal Vasko2e7241e2016-02-15 16:06:34 +01005239 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", (*submodule)->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005240
Michal Vasko9f258e42016-02-11 11:36:27 +01005241 /* warn about applied deviations */
Michal Vasko2e7241e2016-02-15 16:06:34 +01005242 for (i = 0; i < (*submodule)->deviation_size; ++i) {
5243 if ((*submodule)->deviation[i].target_module) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005244 LOGERR(ly_errno, "Submodule parsing failed, but successfully deviated %smodule \"%s\".",
Michal Vasko2e7241e2016-02-15 16:06:34 +01005245 ((*submodule)->deviation[i].target_module->type ? "sub" : ""),
5246 (*submodule)->deviation[i].target_module->name);
Michal Vasko9f258e42016-02-11 11:36:27 +01005247 }
5248 }
5249
5250 /* remove applied augments */
Michal Vasko2e7241e2016-02-15 16:06:34 +01005251 for (i = 0; i < (*submodule)->augment_size; ++i) {
5252 if ((*submodule)->augment[i].target) {
5253 LY_TREE_FOR_SAFE((*submodule)->augment[i].target->child, next, elem) {
5254 if (elem->parent == (struct lys_node *)&(*submodule)->augment[i]) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005255 lys_node_free(elem, NULL);
5256 }
5257 }
5258 }
5259 }
5260
Michal Vasko2e7241e2016-02-15 16:06:34 +01005261 /* leave unres and (*submodule) allocated for now */
5262 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005263}
5264
Michal Vasko0d343d12015-08-24 14:57:36 +02005265/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005266struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005267yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005268{
Michal Vasko9f258e42016-02-11 11:36:27 +01005269 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005271 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005272 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 const char *value;
5274 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005275
Radek Krejcic071c542016-01-27 14:57:51 +01005276 unres = calloc(1, sizeof *unres);
5277 if (!unres) {
5278 LOGMEM;
5279 return NULL;
5280 }
5281
Radek Krejci722b0072016-02-01 17:09:45 +01005282 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005283 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005284 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005287 /* check root element */
5288 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejciadb57612016-02-16 13:34:34 +01005289 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005290 goto error;
5291 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005294 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005295 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 goto error;
5297 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005299 module = calloc(1, sizeof *module);
5300 if (!module) {
5301 LOGMEM;
5302 goto error;
5303 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005305 module->ctx = ctx;
5306 module->name = lydict_insert(ctx, value, strlen(value));
5307 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005308 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005309
Michal Vasko9f258e42016-02-11 11:36:27 +01005310 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005311 if (read_sub_module(module, NULL, yin, unres)) {
5312 goto error;
5313 }
5314
5315 /* resolve rest of unres items */
5316 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005317 goto error;
5318 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005320 /* add to the context's list of modules */
5321 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005322 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005323 if (!newlist) {
5324 LOGMEM;
5325 goto error;
5326 }
5327 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5328 newlist[i] = NULL;
5329 }
5330 ctx->models.size *= 2;
5331 ctx->models.list = newlist;
5332 }
5333 for (i = 0; ctx->models.list[i]; i++) {
5334 /* check name (name/revision) and namespace uniqueness */
5335 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005336 if (ctx->models.list[i]->rev_size == module->rev_size) {
5337 /* both have the same number of revisions */
5338 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5339 /* both have the same revision -> we already have the same module */
5340 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005341 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005342
Michal Vasko9f258e42016-02-11 11:36:27 +01005343 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005344 module = ctx->models.list[i];
5345 if (implement && !module->implemented) {
5346 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005347 }
Radek Krejcic071c542016-01-27 14:57:51 +01005348
5349 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 }
5351 }
Radek Krejcif647e612015-07-30 11:36:07 +02005352 /* else (both elses) keep searching, for now the caller is just adding
5353 * another revision of an already present schema
5354 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005356 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 ctx->models.list[i]->name, module->name, module->ns);
5358 goto error;
5359 }
5360 }
5361 ctx->models.list[i] = module;
5362 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005363 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005364
Radek Krejcic071c542016-01-27 14:57:51 +01005365success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005367 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005368 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005369
Michal Vasko9f258e42016-02-11 11:36:27 +01005370 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005372 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005373
5374error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005375 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005376 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005377 unres_schema_free(module, &unres);
5378
5379 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005380 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005381 return NULL;
5382 }
5383
5384 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005385
Michal Vasko9f258e42016-02-11 11:36:27 +01005386 /* warn about applied deviations */
5387 for (i = 0; i < module->deviation_size; ++i) {
Michal Vasko60f4b452016-02-12 11:02:55 +01005388 if (module->deviation[i].target_module) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005389 LOGERR(ly_errno, "Module parsing failed, but successfully deviated %smodule \"%s\".",
Michal Vasko60f4b452016-02-12 11:02:55 +01005390 (module->deviation[i].target_module->type ? "sub" : ""),
5391 module->deviation[i].target_module->name);
Michal Vasko9f258e42016-02-11 11:36:27 +01005392 }
5393 }
5394
5395 /* remove applied augments */
5396 for (i = 0; i < module->augment_size; ++i) {
5397 if (module->augment[i].target) {
5398 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5399 if (elem->parent == (struct lys_node *)&module->augment[i]) {
5400 lys_node_free(elem, NULL);
5401 }
5402 }
5403 }
5404 }
5405
5406 lys_free(module, NULL, 1);
5407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005408 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005409}