blob: 731df0e2fc1865fb5be618566e1e1a5b90e9525e [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 Vasko217db072016-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 Krejci6e4ffbb2015-06-16 10:34:41 +0200245 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200246 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200247
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200248 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200249 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200250 if (!value) {
251 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200252 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200253
254 i = parse_identifier(value);
255 if (i < 1) {
Radek Krejciadb57612016-02-16 13:34:34 +0100256 LOGVAL(LYE_INCHAR, LOGLINE(yin), LY_VLOG_XML, yin, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100257 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200258 goto error;
259 }
260 /* module name */
261 if (value[i]) {
262 type->module_name = lydict_insert(module->ctx, value, i);
263 value += i;
Michal Vasko534f8442015-10-21 13:25:49 +0200264 if ((value[0] != ':') || (parse_identifier(value + 1) < 1)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100265 LOGVAL(LYE_INCHAR, LOGLINE(yin), LY_VLOG_XML, yin, value[0], value);
Michal Vasko88c29542015-11-27 14:57:53 +0100266 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200267 goto error;
268 }
Michal Vasko534f8442015-10-21 13:25:49 +0200269 ++value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200270 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200271
Michal Vasko1dca6882015-10-22 14:29:42 +0200272 rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100273 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200274 if (rc == -1) {
Radek Krejciadb57612016-02-16 13:34:34 +0100275 LOGVAL(LYE_INMOD, LOGLINE(yin), LY_VLOG_XML, yin, type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200276 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100277
278 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200279 } else if (rc == EXIT_FAILURE) {
Michal Vasko88c29542015-11-27 14:57:53 +0100280 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200281 }
282 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200283
Radek Krejcicf509982015-12-15 09:22:44 +0100284 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100285 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejciadb57612016-02-16 13:34:34 +0100286 type->der->flags, type->der->module, type->der->name, LOGLINE(yin), parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100287 return -1;
288 }
289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200290 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200291 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200292 /* RFC 6020 9.7.4 - bit */
293
294 /* get bit specifications, at least one must be present */
295 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200296 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
297 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100298 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200299 continue;
300 }
301
Radek Krejci994b6f62015-06-18 16:47:27 +0200302 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200303 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200304 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100305 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200306 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200307 }
308 }
Radek Krejciac781922015-07-09 15:35:14 +0200309 if (!type->der->type.der && !type->info.bits.count) {
310 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejciadb57612016-02-16 13:34:34 +0100311 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200312 goto error;
313 }
Radek Krejciac781922015-07-09 15:35:14 +0200314 if (type->der->type.der && type->info.bits.count) {
315 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejciadb57612016-02-16 13:34:34 +0100316 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200317 goto error;
318 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200319
320 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100321 if (!type->info.bits.bit) {
322 LOGMEM;
323 goto error;
324 }
Radek Krejci73adb602015-07-02 18:07:40 +0200325 p = 0;
326 i = -1;
327 LY_TREE_FOR(yin->child, next) {
328 i++;
329
330 GETVAL(value, next, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100331 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100332 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, next);
Michal Vasko2d26a022015-12-07 09:27:21 +0100333 goto error;
334 }
335
Radek Krejci994b6f62015-06-18 16:47:27 +0200336 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200337 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200338 type->info.bits.count = i + 1;
339 goto error;
340 }
341
342 /* check the name uniqueness */
343 for (j = 0; j < i; j++) {
344 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100345 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), LY_VLOG_XML, next, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200346 type->info.bits.count = i + 1;
347 goto error;
348 }
349 }
350
Radek Krejci0d70c372015-07-02 16:23:10 +0200351 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200352 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200353 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
354 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200355 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200356 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200357
Radek Krejci0d70c372015-07-02 16:23:10 +0200358 if (!strcmp(node->name, "position")) {
359 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200360 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200361
362 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200363 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100364 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200365 type->info.bits.count = i + 1;
366 goto error;
367 }
368 type->info.bits.bit[i].pos = (uint32_t)p_;
369
370 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200371 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200372 p = type->info.bits.bit[i].pos;
373 p++;
374 } else {
375 /* check that the value is unique */
376 for (j = 0; j < i; j++) {
377 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejciadb57612016-02-16 13:34:34 +0100378 LOGVAL(LYE_BITS_DUPVAL, LOGLINE(node), LY_VLOG_XML, node,
379 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200380 type->info.bits.count = i + 1;
381 goto error;
382 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200383 }
384 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200385 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100386 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200387 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200388 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200389 }
390 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200391 /* assign value automatically */
392 if (p > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100393 LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_XML, next, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200394 type->info.bits.count = i + 1;
395 goto error;
396 }
397 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100398 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200399 p++;
400 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200401
402 /* keep them ordered by position */
403 j = i;
404 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
405 /* switch them */
406 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
407 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
408 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
409 j--;
410 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200411 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200412 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200414 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200415 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200416 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200417 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
418 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200419 continue;
420 }
421
Radek Krejcif9401c32015-06-26 16:47:36 +0200422 if (!strcmp(node->name, "range")) {
423 if (type->info.dec64.range) {
Radek Krejciadb57612016-02-16 13:34:34 +0100424 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200425 goto error;
426 }
427
428 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200429 if (lyp_check_length_range(value, type)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100430 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200431 goto error;
432 }
433 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100434 if (!type->info.dec64.range) {
435 LOGMEM;
436 goto error;
437 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200438 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
439
440 /* get possible substatements */
441 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
442 goto error;
443 }
444 } else if (!strcmp(node->name, "fraction-digits")) {
445 if (type->info.dec64.dig) {
Radek Krejciadb57612016-02-16 13:34:34 +0100446 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200447 goto error;
448 }
449 GETVAL(value, node, "value");
450 v = strtol(value, NULL, 10);
451
452 /* range check */
453 if (v < 1 || v > 18) {
Radek Krejciadb57612016-02-16 13:34:34 +0100454 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200455 goto error;
456 }
457 type->info.dec64.dig = (uint8_t)v;
458 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100459 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200460 goto error;
461 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200462 }
463
464 /* mandatory sub-statement(s) check */
465 if (!type->info.dec64.dig && !type->der->type.der) {
466 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejciadb57612016-02-16 13:34:34 +0100467 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200468 goto error;
469 }
Radek Krejci7511f402015-07-10 09:56:30 +0200470 if (type->info.dec64.dig && type->der->type.der) {
471 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejciadb57612016-02-16 13:34:34 +0100472 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200473 goto error;
474 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200475 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200478 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200479
Radek Krejci994b6f62015-06-18 16:47:27 +0200480 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200481 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200482 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
483 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100484 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200485 continue;
486 }
487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200488 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200490 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100491 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200492 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200493 }
494 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200495 if (!type->der->type.der && !type->info.enums.count) {
496 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejciadb57612016-02-16 13:34:34 +0100497 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200498 goto error;
499 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200500 if (type->der->type.der && type->info.enums.count) {
501 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejciadb57612016-02-16 13:34:34 +0100502 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200503 goto error;
504 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200505
Radek Krejci1574a8d2015-08-03 14:16:52 +0200506 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100507 if (!type->info.enums.enm) {
508 LOGMEM;
509 goto error;
510 }
Radek Krejci73adb602015-07-02 18:07:40 +0200511 v = 0;
512 i = -1;
513 LY_TREE_FOR(yin->child, next) {
514 i++;
515
516 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100517 if (!value[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +0100518 LOGVAL(LYE_SPEC, LOGLINE(next), LY_VLOG_XML, next, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100519 goto error;
520 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200521 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200522 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200523 type->info.enums.count = i + 1;
524 goto error;
525 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200527 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200528 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200529 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejciadb57612016-02-16 13:34:34 +0100530 LOGVAL(LYE_ENUM_WS, LOGLINE(next), LY_VLOG_XML, next, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200531 type->info.enums.count = i + 1;
532 goto error;
533 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200535 /* check the name uniqueness */
536 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200537 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100538 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), LY_VLOG_XML, next, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200539 type->info.enums.count = i + 1;
540 goto error;
541 }
542 }
Radek Krejci04581c62015-05-22 21:24:00 +0200543
Radek Krejci0d70c372015-07-02 16:23:10 +0200544 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200545 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200546 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
547 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200548 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200549 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200550
Radek Krejci0d70c372015-07-02 16:23:10 +0200551 if (!strcmp(node->name, "value")) {
552 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200553 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200554
555 /* range check */
556 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100557 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200558 type->info.enums.count = i + 1;
559 goto error;
560 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200561 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200562
563 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200564 if (type->info.enums.enm[i].value > v) {
565 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200566 v++;
567 } else {
568 /* check that the value is unique */
569 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200570 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejciadb57612016-02-16 13:34:34 +0100571 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), LY_VLOG_XML, node,
572 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200573 type->info.enums.count = i + 1;
574 goto error;
575 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200576 }
577 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200578 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100579 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200582 }
583 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 /* assign value automatically */
585 if (v > INT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +0100586 LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_XML, next, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 type->info.enums.count = i + 1;
588 goto error;
589 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200590 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100591 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 v++;
593 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 }
595 break;
596
597 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200598 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599
600 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200601 LY_TREE_FOR_SAFE(yin->child, next, node) {
602 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
603 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100604 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200605 continue;
606 }
607
Michal Vaskoe29c6622015-11-27 15:02:31 +0100608 if (strcmp(node->name, "base")) {
Radek Krejciadb57612016-02-16 13:34:34 +0100609 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200610 goto error;
611 }
612 }
613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200614 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200615 if (type->der->type.der) {
616 /* this is just a derived type with no base specified/required */
617 break;
618 }
Radek Krejciadb57612016-02-16 13:34:34 +0100619 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620 goto error;
621 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 if (yin->child->next) {
Radek Krejciadb57612016-02-16 13:34:34 +0100623 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), LY_VLOG_XML, yin->child->next,
624 yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200625 goto error;
626 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200627 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100628 /* store in the JSON format */
629 value = transform_schema2json(module, value, LOGLINE(yin->child));
630 if (!value) {
631 goto error;
632 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200633 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200634 goto error;
635 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 break;
637
638 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200639 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200640 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200641 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
642 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200643 continue;
644 }
645
Radek Krejciaf351422015-06-19 14:49:38 +0200646 if (!strcmp(node->name, "require-instance")) {
647 if (type->info.inst.req) {
Radek Krejciadb57612016-02-16 13:34:34 +0100648 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200649 goto error;
650 }
651 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200652 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200653 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200654 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200655 type->info.inst.req = -1;
656 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100657 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200658 goto error;
659 }
660 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100661 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200662 goto error;
663 }
Radek Krejciaf351422015-06-19 14:49:38 +0200664 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200666 break;
667
Radek Krejcif2860132015-06-20 12:37:20 +0200668 case LY_TYPE_BINARY:
669 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200670 case LY_TYPE_INT8:
671 case LY_TYPE_INT16:
672 case LY_TYPE_INT32:
673 case LY_TYPE_INT64:
674 case LY_TYPE_UINT8:
675 case LY_TYPE_UINT16:
676 case LY_TYPE_UINT32:
677 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200678 /* RFC 6020 9.2.4 - range */
679
680 /* length and range are actually the same restriction, so process
681 * them by this common code, we just need to differ the name and
682 * structure where the information will be stored
683 */
684 if (type->base == LY_TYPE_BINARY) {
685 restr = &type->info.binary.length;
686 name = "length";
687 } else {
688 restr = &type->info.num.range;
689 name = "range";
690 }
691
Radek Krejci73adb602015-07-02 18:07:40 +0200692 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200693 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
694 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200695 continue;
696 }
697
Radek Krejcif2860132015-06-20 12:37:20 +0200698 if (!strcmp(node->name, name)) {
699 if (*restr) {
Radek Krejciadb57612016-02-16 13:34:34 +0100700 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200701 goto error;
702 }
703
704 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200705 if (lyp_check_length_range(value, type)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100706 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200707 goto error;
708 }
709 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100710 if (!(*restr)) {
711 LOGMEM;
712 goto error;
713 }
Radek Krejcif2860132015-06-20 12:37:20 +0200714 (*restr)->expr = lydict_insert(module->ctx, value, 0);
715
716 /* get possible substatements */
717 if (read_restr_substmt(module->ctx, *restr, node)) {
718 goto error;
719 }
720 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100721 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200722 goto error;
723 }
Radek Krejcif2860132015-06-20 12:37:20 +0200724 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 break;
726
727 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200728 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200729 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200730 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
731 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200732 continue;
733 }
734
Michal Vasko88c29542015-11-27 14:57:53 +0100735 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200736 if (type->info.lref.path) {
Radek Krejciadb57612016-02-16 13:34:34 +0100737 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200738 goto error;
739 }
740
741 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200742 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200743 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200744 if (!type->info.lref.path) {
745 goto error;
746 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200747 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200748 goto error;
749 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200750
Radek Krejcidc4c1412015-06-19 15:39:54 +0200751 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100752 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200753 goto error;
754 }
Radek Krejci73adb602015-07-02 18:07:40 +0200755 }
756
Michal Vasko88c29542015-11-27 14:57:53 +0100757 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejciadb57612016-02-16 13:34:34 +0100758 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200759 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200760 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200761 break;
762
763 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200764 /* RFC 6020 9.4.4 - length */
765 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200766 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200767 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200768 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
769 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100770 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200771 continue;
772 }
773
Radek Krejci3733a802015-06-19 13:43:21 +0200774 if (!strcmp(node->name, "length")) {
775 if (type->info.str.length) {
Radek Krejciadb57612016-02-16 13:34:34 +0100776 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200777 goto error;
778 }
779
780 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200781 if (lyp_check_length_range(value, type)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100782 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200783 goto error;
784 }
785 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100786 if (!type->info.str.length) {
787 LOGMEM;
788 goto error;
789 }
Radek Krejci3733a802015-06-19 13:43:21 +0200790 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
791
Radek Krejci5fbc9162015-06-19 14:11:11 +0200792 /* get possible sub-statements */
793 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200794 goto error;
795 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100796 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200797 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200798 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200799 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100800 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200801 goto error;
802 }
803 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200804 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200805 if (i) {
806 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100807 if (!type->info.str.patterns) {
808 LOGMEM;
809 goto error;
810 }
Radek Krejci73adb602015-07-02 18:07:40 +0200811 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100812 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200813
814 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200815 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
816 if (!precomp) {
Radek Krejciadb57612016-02-16 13:34:34 +0100817 LOGVAL(LYE_INREGEX, LOGLINE(node), LY_VLOG_XML, node, value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200818 free(type->info.str.patterns);
819 goto error;
820 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200821 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200822
Radek Krejci73adb602015-07-02 18:07:40 +0200823 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200824
825 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100826 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200827 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200828 goto error;
829 }
Radek Krejci73adb602015-07-02 18:07:40 +0200830 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200831 }
832 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200833 break;
834
835 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200836 /* RFC 6020 7.4 - type */
837 /* count number of types in union */
838 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200839 LY_TREE_FOR_SAFE(yin->child, next, node) {
840 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
841 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100842 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200843 continue;
844 }
845
Radek Krejcie4c366b2015-07-02 10:11:31 +0200846 if (!strcmp(node->name, "type")) {
847 i++;
848 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100849 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200850 goto error;
851 }
852 }
853
854 if (!i) {
855 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100856 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200857 break;
858 }
Radek Krejciadb57612016-02-16 13:34:34 +0100859 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200860 goto error;
861 }
862
863 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200864 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100865 if (!type->info.uni.types) {
866 LOGMEM;
867 goto error;
868 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200869 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200870 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100871 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100872 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
873 if (!rc) {
874 type->info.uni.count++;
875
876 /* union's type cannot be empty or leafref */
877 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejciadb57612016-02-16 13:34:34 +0100878 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100879 rc = -1;
880 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejciadb57612016-02-16 13:34:34 +0100881 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100882 rc = -1;
883 }
884 }
885 if (rc) {
886 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
887 for (i = 0; i < type->info.uni.count; ++i) {
888 lys_type_free(module->ctx, &type->info.uni.types[i]);
889 }
890 free(type->info.uni.types);
891 type->info.uni.types = NULL;
892 type->info.uni.count = 0;
893
894 if (rc == EXIT_FAILURE) {
895 return EXIT_FAILURE;
896 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200897 goto error;
898 }
Michal Vasko88c29542015-11-27 14:57:53 +0100899 }
900 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200901
Michal Vasko88c29542015-11-27 14:57:53 +0100902 case LY_TYPE_BOOL:
903 case LY_TYPE_EMPTY:
904 /* no sub-statement allowed */
905 LY_TREE_FOR(yin->child, node) {
906 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100907 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200908 goto error;
909 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 break;
912
913 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100914 LOGINT;
915 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916 }
917
918 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200919
920error:
Michal Vasko88c29542015-11-27 14:57:53 +0100921 return -1;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200922}
923
Michal Vasko0d343d12015-08-24 14:57:36 +0200924/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200926fill_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 +0200927{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200928 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100929 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200930 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100933 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100934 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 goto error;
936 }
937 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +0200940 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 goto error;
942 }
Radek Krejcieac35532015-05-31 19:09:15 +0200943
Michal Vasko88c29542015-11-27 14:57:53 +0100944 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200945 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
946 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200947 continue;
948 }
949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100951 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +0100952 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 goto error;
954 }
Michal Vasko88c29542015-11-27 14:57:53 +0100955 /* HACK for unres */
956 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100957 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100958 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200959 goto error;
960 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200961 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 } else if (!strcmp(node->name, "default")) {
963 if (tpdf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +0100964 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 goto error;
966 }
967 GETVAL(value, node, "value");
968 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200969 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970 } else if (!strcmp(node->name, "units")) {
971 if (tpdf->units) {
Radek Krejciadb57612016-02-16 13:34:34 +0100972 LOGVAL(LYE_TOOMANY, LOGLINE(node), LY_VLOG_XML, node, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 goto error;
974 }
975 GETVAL(value, node, "name");
976 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
977 } else {
Radek Krejciadb57612016-02-16 13:34:34 +0100978 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 goto error;
980 }
981 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200984 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +0100985 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200986 goto error;
987 }
Radek Krejcieac35532015-05-31 19:09:15 +0200988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200990 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +0200991 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200992 goto error;
993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200997
998error:
999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001001}
1002
Michal Vasko0d343d12015-08-24 14:57:36 +02001003/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001004static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001005fill_yin_feature(struct lys_module *module, struct lyxml_elem *yin, struct lys_feature *f, struct unres_schema *unres)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001006{
1007 const char *value;
1008 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001009 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001010
Radek Krejcib05774c2015-06-18 13:52:59 +02001011 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01001012 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001013 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejcib05774c2015-06-18 13:52:59 +02001014 goto error;
1015 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001016 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001017 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001018
Radek Krejci76512572015-08-04 09:47:08 +02001019 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001020 goto error;
1021 }
1022
1023 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001024 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1025 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001026 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001027 continue;
1028 }
1029
Radek Krejci3cf9e222015-06-18 11:37:50 +02001030 if (!strcmp(child->name, "if-feature")) {
1031 c++;
1032 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001033 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001034 goto error;
1035 }
1036 }
1037
1038 if (c) {
1039 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001040 if (!f->features) {
1041 LOGMEM;
1042 goto error;
1043 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001044 }
Radek Krejci73adb602015-07-02 18:07:40 +02001045 LY_TREE_FOR(yin->child, child) {
Michal Vasko217db072016-02-15 12:32:04 +01001046 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001047 f->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01001048 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001049 goto error;
1050 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001051 }
1052
Radek Krejci3cf9e222015-06-18 11:37:50 +02001053 return EXIT_SUCCESS;
1054
1055error:
1056
1057 return EXIT_FAILURE;
1058}
1059
Michal Vasko0d343d12015-08-24 14:57:36 +02001060/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001061static int
Radek Krejcib8048692015-08-05 13:36:34 +02001062fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001063{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001064 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001067 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001068 if (!must->expr) {
1069 goto error;
1070 }
Michal Vasko27f2da82016-02-15 12:32:42 +01001071 if (lyxp_syntax_check(must->expr, LOGLINE(yin))) {
1072 goto error;
1073 }
Radek Krejci800af702015-06-02 13:46:01 +02001074
Radek Krejci41726f92015-06-19 13:11:05 +02001075 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001076
Michal Vasko27f2da82016-02-15 12:32:42 +01001077error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001079}
1080
Radek Krejci581ce772015-11-10 17:22:40 +01001081static int
Michal Vasko88c29542015-11-27 14:57:53 +01001082fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1083 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001084{
1085 int i, j;
1086 const char *value, *vaux;
1087
1088 /* get unique value (list of leafs supposed to be unique */
1089 GETVAL(value, yin, "tag");
1090
1091 /* count the number of unique leafs in the value */
1092 vaux = value;
1093 while ((vaux = strpbrk(vaux, " \t\n"))) {
1094 unique->expr_size++;
1095 while (isspace(*vaux)) {
1096 vaux++;
1097 }
1098 }
1099 unique->expr_size++;
1100 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001101 if (!unique->expr) {
1102 LOGMEM;
1103 goto error;
1104 }
Radek Krejci581ce772015-11-10 17:22:40 +01001105
1106 for (i = 0; i < unique->expr_size; i++) {
1107 vaux = strpbrk(value, " \t\n");
1108 if (!vaux) {
1109 /* the last token, lydict_insert() will count its size on its own */
1110 vaux = value;
1111 }
1112
1113 /* store token into unique structure */
1114 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1115
1116 /* check that the expression does not repeat */
1117 for (j = 0; j < i; j++) {
1118 if (unique->expr[j] == unique->expr[i]) {
Radek Krejciadb57612016-02-16 13:34:34 +01001119 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, unique->expr[i], "unique");
1120 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001121 goto error;
1122 }
1123 }
1124
1125 /* try to resolve leaf */
1126 if (unres) {
1127 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1128 } else {
1129 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1130 goto error;
1131 }
1132 }
1133
1134 /* move to next token */
1135 value = vaux;
1136 while(isspace(*value)) {
1137 value++;
1138 }
1139 }
1140
1141 return EXIT_SUCCESS;
1142
1143error:
1144 return EXIT_FAILURE;
1145}
1146
Michal Vasko0d343d12015-08-24 14:57:36 +02001147/* logs directly
1148 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001149 * type: 0 - min, 1 - max
1150 */
1151static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001152deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001153{
1154 const char *value;
1155 char *endptr;
1156 unsigned long val;
1157 uint32_t *ui32val;
1158
1159 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001160 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001161 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001162 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001163 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001164 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001165 }
Radek Krejci76512572015-08-04 09:47:08 +02001166 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001167 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001168 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001169 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001170 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001171 }
1172 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001173 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
1174 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001175 goto error;
1176 }
1177
1178 GETVAL(value, node, "value");
1179 while (isspace(value[0])) {
1180 value++;
1181 }
1182
Radek Krejci0d7b2472016-02-12 11:11:03 +01001183 if (type && !strcmp(value, "unbounded")) {
1184 d->max = val = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001185 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001186 /* convert it to uint32_t */
1187 errno = 0;
1188 endptr = NULL;
1189 val = strtoul(value, &endptr, 10);
1190 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01001191 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001192 goto error;
1193 }
1194 if (type) {
1195 d->max = (uint32_t)val;
1196 } else {
1197 d->min = (uint32_t)val;
1198 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001199 }
1200
1201 if (d->mod == LY_DEVIATE_ADD) {
1202 /* check that there is no current value */
1203 if (*ui32val) {
Radek Krejciadb57612016-02-16 13:34:34 +01001204 LOGVAL(LYE_INSTMT, LOGLINE(node), LY_VLOG_XML, node, node->name);
1205 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001206 goto error;
1207 }
1208 }
1209
1210 if (d->mod == LY_DEVIATE_DEL) {
1211 /* check values */
1212 if ((uint32_t)val != *ui32val) {
Radek Krejciadb57612016-02-16 13:34:34 +01001213 LOGVAL(LYE_INARG, LOGLINE(node), LY_VLOG_XML, node, value, node->name);
1214 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001215 goto error;
1216 }
1217 /* remove current min-elements value of the target */
1218 *ui32val = 0;
1219 } else { /* add (already checked) and replace */
1220 /* set new value specified in deviation */
1221 *ui32val = (uint32_t)val;
1222 }
1223
1224 return EXIT_SUCCESS;
1225
1226error:
1227
1228 return EXIT_FAILURE;
1229}
1230
Michal Vasko0d343d12015-08-24 14:57:36 +02001231/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001232static int
Michal Vasko88c29542015-11-27 14:57:53 +01001233fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1234 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001235{
1236 const char *value, **stritem;
1237 struct lyxml_elem *next, *child, *develem;
1238 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001239 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001240 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001241 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001242 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001243 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001244 struct lys_node_choice *choice = NULL;
1245 struct lys_node_leaf *leaf = NULL;
1246 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001247 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001248 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001249 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001250 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001251
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001252 ctx = module->ctx;
1253
Radek Krejcieb00f512015-07-01 16:44:58 +02001254 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001255 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001256 if (!dev->target_name) {
1257 goto error;
1258 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001259
1260 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001261 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1262 if (rc || !dev_target) {
Radek Krejciadb57612016-02-16 13:34:34 +01001263 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001264 goto error;
1265 }
Michal Vaskob7b068c2016-02-16 13:51:50 +01001266 if (dev_target->module == lys_module(module)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001267 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001268 goto error;
1269 }
1270 /* mark the target module as deviated */
Michal Vaskoff006c12016-02-17 11:15:19 +01001271 dev_target->module->deviated = 1;
1272
1273 /* copy our imports to the deviated module (deviations may need them to work) */
1274 for (i = 0; i < module->imp_size; ++i) {
1275 for (j = 0; j < dev_target->module->imp_size; ++j) {
1276 if (module->imp[i].module == dev_target->module->imp[j].module) {
1277 break;
1278 }
1279 }
1280
1281 if (j < dev_target->module->imp_size) {
1282 /* import is already there */
1283 continue;
1284 }
1285
1286 /* copy the import, mark it as external */
1287 ++dev_target->module->imp_size;
1288 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1289 if (!dev_target->module->imp) {
1290 LOGMEM;
1291 goto error;
1292 }
1293 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1294 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1295 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1296 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1297 }
1298
1299 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1300 for (i = 0; i < dev_target->module->imp_size; ++i) {
1301 if (dev_target->module->imp[i].module == module) {
1302 break;
1303 }
1304 }
1305
1306 if (i == dev_target->module->imp_size) {
1307 ++dev_target->module->imp_size;
1308 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1309 if (!dev_target->module->imp) {
1310 LOGMEM;
1311 goto error;
1312 }
1313 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1314 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1315 if (module->rev_size) {
1316 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1317 } else {
1318 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1319 }
1320 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1321 } else {
1322 /* it could have been added by another deviating module that imported this deviating module */
1323 dev_target->module->imp[i].external = 2;
1324 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001325
1326 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001327 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1328 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001329 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001330 continue;
1331 }
1332
Radek Krejcieb00f512015-07-01 16:44:58 +02001333 if (!strcmp(child->name, "description")) {
1334 if (dev->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01001335 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001336 goto error;
1337 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001338 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001339 if (!dev->dsc) {
1340 goto error;
1341 }
1342 } else if (!strcmp(child->name, "reference")) {
1343 if (dev->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01001344 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001345 goto error;
1346 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001347 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001348 if (!dev->ref) {
1349 goto error;
1350 }
1351 } else if (!strcmp(child->name, "deviate")) {
1352 c_dev++;
1353
Michal Vasko345da0a2015-12-02 10:35:55 +01001354 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001355 * further processed later
1356 */
1357 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001358
Radek Krejcieb00f512015-07-01 16:44:58 +02001359 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001360 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001361 goto error;
1362 }
1363
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001364 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001365 }
1366
1367 if (c_dev) {
1368 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001369 if (!dev->deviate) {
1370 LOGMEM;
1371 goto error;
1372 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 }
1374
1375 LY_TREE_FOR(yin->child, develem) {
1376 /* init */
1377 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001378 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001379 c_must = 0;
1380 c_uniq = 0;
1381
1382 /* get deviation type */
1383 GETVAL(value, develem, "value");
1384 if (!strcmp(value, "not-supported")) {
1385 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1386 /* no property expected in this case */
1387 if (develem->child) {
Radek Krejciadb57612016-02-16 13:34:34 +01001388 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), LY_VLOG_XML, develem->child, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001389 goto error;
1390 }
1391
Radek Krejci5b917642015-07-02 09:03:13 +02001392 /* and neither any other deviate statement is expected,
1393 * not-supported deviation must be the only deviation of the target
1394 */
1395 if (dev->deviate_size || develem->next) {
Radek Krejciadb57612016-02-16 13:34:34 +01001396 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
1397 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001398 goto error;
1399 }
1400
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001401 /* you cannot remove a key leaf */
1402 if ((dev_target->nodetype == LYS_LEAF) && dev_target->parent && (dev_target->parent->nodetype == LYS_LIST)) {
1403 for (i = 0; i < ((struct lys_node_list *)dev_target->parent)->keys_size; ++i) {
1404 if (((struct lys_node_list *)dev_target->parent)->keys[i] == (struct lys_node_leaf *)dev_target) {
1405 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
1406 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot remove a list key.");
1407 goto error;
1408 }
1409 }
1410 }
Radek Krejci5b917642015-07-02 09:03:13 +02001411
Michal Vaskoff006c12016-02-17 11:15:19 +01001412 /* unlink and store the original node */
1413 lys_node_unlink(dev_target);
1414 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415
Radek Krejci5b917642015-07-02 09:03:13 +02001416 dev->deviate_size = 1;
1417 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 } else if (!strcmp(value, "add")) {
1419 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1420 } else if (!strcmp(value, "replace")) {
1421 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1422 } else if (!strcmp(value, "delete")) {
1423 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1424 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001425 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001426 goto error;
1427 }
1428 d = &dev->deviate[dev->deviate_size];
1429
Michal Vaskoff006c12016-02-17 11:15:19 +01001430 /* store a shallow copy of the original node */
1431 if (!dev->orig_node) {
1432 memset(&tmp_unres, 0, sizeof tmp_unres);
1433 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1434 /* just to be safe */
1435 if (tmp_unres.count) {
1436 LOGINT;
1437 goto error;
1438 }
1439 }
1440
Radek Krejcieb00f512015-07-01 16:44:58 +02001441 /* process deviation properties */
1442 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001443 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1444 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001445 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001446 continue;
1447 }
1448
Radek Krejcieb00f512015-07-01 16:44:58 +02001449 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001450 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001451 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001452 goto error;
1453 }
1454
1455 /* for we deviate from RFC 6020 and allow config property even it is/is not
1456 * specified in the target explicitly since config property inherits. So we expect
1457 * that config is specified in every node. But for delete, we check that the value
1458 * is the same as here in deviation
1459 */
1460 GETVAL(value, child, "value");
1461 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001462 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001463 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001464 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001465 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001466 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001467 goto error;
1468 }
1469
1470 if (d->mod == LY_DEVIATE_DEL) {
1471 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001472 if ((d->flags & LYS_CONFIG_MASK) != (dev_target->flags & LYS_CONFIG_MASK)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001473 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1474 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001475 goto error;
1476 }
1477 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001478 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001479
1480 /* ... and inherit config value from the target's parent */
Michal Vasko60f4b452016-02-12 11:02:55 +01001481 if (dev_target->parent) {
1482 dev_target->flags |= dev_target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001483 } else {
1484 /* default config is true */
Michal Vasko60f4b452016-02-12 11:02:55 +01001485 dev_target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 }
1487 } else { /* add and replace are the same in this case */
1488 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001489 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001490
1491 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001492 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001493 }
1494 } else if (!strcmp(child->name, "default")) {
1495 if (d->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001496 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001497 goto error;
1498 }
1499 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001500 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001501
Michal Vasko60f4b452016-02-12 11:02:55 +01001502 if (dev_target->nodetype == LYS_CHOICE) {
1503 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001504
1505 if (d->mod == LY_DEVIATE_ADD) {
1506 /* check that there is no current value */
1507 if (choice->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001508 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1509 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001510 goto error;
1511 }
1512 }
1513
Michal Vasko3edeaf72016-02-11 13:17:43 +01001514 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001515 if (rc || !node) {
Radek Krejciadb57612016-02-16 13:34:34 +01001516 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001517 goto error;
1518 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001520 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001521 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1522 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001523 goto error;
1524 }
1525 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001526 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001527 if (!choice->dflt) {
1528 /* default branch not found */
Radek Krejciadb57612016-02-16 13:34:34 +01001529 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001530 goto error;
1531 }
1532 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001533 } else if (dev_target->nodetype == LYS_LEAF) {
1534 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001535
1536 if (d->mod == LY_DEVIATE_ADD) {
1537 /* check that there is no current value */
1538 if (leaf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001539 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1540 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001541 goto error;
1542 }
1543 }
1544
1545 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001546 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001547 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1548 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001549 goto error;
1550 }
1551 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001552 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001553 leaf->dflt = NULL;
1554 } else { /* add (already checked) and replace */
1555 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001556 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001557
1558 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001559 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001560 }
1561 } else {
1562 /* invalid target for default value */
Radek Krejciadb57612016-02-16 13:34:34 +01001563 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1564 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001565 goto error;
1566 }
1567 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001568 if (d->flags & LYS_MAND_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001569 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001570 goto error;
1571 }
1572
1573 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001574 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejciadb57612016-02-16 13:34:34 +01001575 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1576 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001577 goto error;
1578 }
1579
1580 GETVAL(value, child, "value");
1581 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001582 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001583 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001584 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001585 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001586 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 goto error;
1588 }
1589
1590 if (d->mod == LY_DEVIATE_ADD) {
1591 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001592 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001593 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1594 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001595 goto error;
1596 }
1597 }
1598
1599 if (d->mod == LY_DEVIATE_DEL) {
1600 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001601 if ((d->flags & LYS_MAND_MASK) != (dev_target->flags & LYS_MAND_MASK)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001602 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1603 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001604 goto error;
1605 }
1606 /* remove current mandatory value of the target */
Michal Vasko60f4b452016-02-12 11:02:55 +01001607 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001608 } else { /* add (already checked) and replace */
1609 /* remove current mandatory value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001610 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001611
1612 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001613 dev_target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001614 }
1615 } else if (!strcmp(child->name, "min-elements")) {
1616 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01001617 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001618 goto error;
1619 }
1620 f_min = 1;
1621
Michal Vasko60f4b452016-02-12 11:02:55 +01001622 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001623 goto error;
1624 }
1625 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001626 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01001627 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001628 goto error;
1629 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001630 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001631
Michal Vasko60f4b452016-02-12 11:02:55 +01001632 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001633 goto error;
1634 }
1635 } else if (!strcmp(child->name, "must")) {
1636 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001637 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 continue;
1639 } else if (!strcmp(child->name, "type")) {
1640 if (d->type) {
Radek Krejciadb57612016-02-16 13:34:34 +01001641 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 goto error;
1643 }
1644
1645 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001646 if (dev_target->nodetype == LYS_LEAF) {
1647 t = &((struct lys_node_leaf *)dev_target)->type;
1648 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1649 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001651 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1652 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 goto error;
1654 }
1655
1656 if (d->mod == LY_DEVIATE_ADD) {
1657 /* not allowed, type is always present at the target */
Radek Krejciadb57612016-02-16 13:34:34 +01001658 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1659 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001660 goto error;
1661 } else if (d->mod == LY_DEVIATE_DEL) {
1662 /* not allowed, type cannot be deleted from the target */
Radek Krejciadb57612016-02-16 13:34:34 +01001663 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1664 LOGVAL(LYE_SPEC, 0, 0, NULL, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 goto error;
1666 }
1667
1668 /* replace */
1669 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001670 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001671
1672 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001673 /* HACK for unres */
1674 t->der = (struct lys_tpdf *)child;
Michal Vasko60f4b452016-02-12 11:02:55 +01001675 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001676 goto error;
1677 }
1678 d->type = t;
1679 } else if (!strcmp(child->name, "unique")) {
1680 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001681 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 continue;
1683 } else if (!strcmp(child->name, "units")) {
1684 if (d->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01001685 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001686 goto error;
1687 }
1688
1689 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001690 if (dev_target->nodetype == LYS_LEAFLIST) {
1691 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1692 } else if (dev_target->nodetype == LYS_LEAF) {
1693 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001694 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001695 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1696 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 goto error;
1698 }
1699
1700 /* get units value */
1701 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001702 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001703
1704 /* apply to target */
1705 if (d->mod == LY_DEVIATE_ADD) {
1706 /* check that there is no current value */
1707 if (*stritem) {
Radek Krejciadb57612016-02-16 13:34:34 +01001708 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1709 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001710 goto error;
1711 }
1712 }
1713
1714 if (d->mod == LY_DEVIATE_DEL) {
1715 /* check values */
1716 if (*stritem != d->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01001717 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1718 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001719 goto error;
1720 }
1721 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001722 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001723 } else { /* add (already checked) and replace */
1724 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001725 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001726
1727 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001728 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 }
1730 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001731 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001732 goto error;
1733 }
1734
Michal Vasko88c29542015-11-27 14:57:53 +01001735 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001736 }
1737
1738 if (c_must) {
1739 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001740 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001741 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001742 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1743 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001744 break;
Radek Krejci76512572015-08-04 09:47:08 +02001745 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001746 trg_must = &((struct lys_node_container *)dev_target)->must;
1747 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001748 break;
Radek Krejci76512572015-08-04 09:47:08 +02001749 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001750 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1751 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001752 break;
Radek Krejci76512572015-08-04 09:47:08 +02001753 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001754 trg_must = &((struct lys_node_list *)dev_target)->must;
1755 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 break;
Radek Krejci76512572015-08-04 09:47:08 +02001757 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001758 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1759 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001760 break;
1761 default:
Radek Krejciadb57612016-02-16 13:34:34 +01001762 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1763 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001764 goto error;
1765 }
1766
1767 if (d->mod == LY_DEVIATE_RPL) {
1768 /* remove target's musts and allocate new array for it */
1769 if (!*trg_must) {
Radek Krejciadb57612016-02-16 13:34:34 +01001770 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, "replace", "deviate");
1771 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001772 goto error;
1773 }
1774
1775 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001776 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001777 }
1778 free(*trg_must);
1779 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1780 d->must_size = c_must;
1781 *trg_must_size = 0;
1782 } else if (d->mod == LY_DEVIATE_ADD) {
1783 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001784 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001785 if (!d->must) {
1786 LOGMEM;
1787 goto error;
1788 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001789 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001790 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 d->must_size = c_must;
1792 } else { /* LY_DEVIATE_DEL */
1793 d->must = calloc(c_must, sizeof *d->must);
1794 }
Michal Vasko253035f2015-12-17 16:58:13 +01001795 if (!d->must) {
1796 LOGMEM;
1797 goto error;
1798 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001799 }
1800 if (c_uniq) {
1801 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001802 if (dev_target->nodetype != LYS_LIST) {
Radek Krejciadb57612016-02-16 13:34:34 +01001803 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1804 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001805 goto error;
1806 }
1807
Michal Vasko60f4b452016-02-12 11:02:55 +01001808 list = (struct lys_node_list *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001809 if (d->mod == LY_DEVIATE_RPL) {
1810 /* remove target's unique and allocate new array for it */
1811 if (!list->unique) {
Radek Krejciadb57612016-02-16 13:34:34 +01001812 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, "replace", "deviate");
1813 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 goto error;
1815 }
1816
1817 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001818 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001819 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001820 }
1821 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001822 }
1823 free(list->unique);
1824 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1825 d->unique_size = c_uniq;
1826 list->unique_size = 0;
1827 } else if (d->mod == LY_DEVIATE_ADD) {
1828 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001829 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001830 list->unique = d->unique;
1831 d->unique = &list->unique[list->unique_size];
1832 d->unique_size = c_uniq;
1833 } else { /* LY_DEVIATE_DEL */
1834 d->unique = calloc(c_uniq, sizeof *d->unique);
1835 }
Michal Vasko253035f2015-12-17 16:58:13 +01001836 if (!d->unique) {
1837 LOGMEM;
1838 goto error;
1839 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001840 }
1841
1842 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001843 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 if (!strcmp(child->name, "must")) {
1845 if (d->mod == LY_DEVIATE_DEL) {
1846 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1847 goto error;
1848 }
1849
1850 /* find must to delete, we are ok with just matching conditions */
1851 for (i = 0; i < *trg_must_size; i++) {
1852 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1853 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001854 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 /* ... and maintain the array */
1856 (*trg_must_size)--;
1857 if (i != *trg_must_size) {
1858 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1859 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1860 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1861 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1862 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1863 }
1864 if (!(*trg_must_size)) {
1865 free(*trg_must);
1866 *trg_must = NULL;
1867 } else {
1868 (*trg_must)[*trg_must_size].expr = NULL;
1869 (*trg_must)[*trg_must_size].dsc = NULL;
1870 (*trg_must)[*trg_must_size].ref = NULL;
1871 (*trg_must)[*trg_must_size].eapptag = NULL;
1872 (*trg_must)[*trg_must_size].emsg = NULL;
1873 }
1874
1875 i = -1; /* set match flag */
1876 break;
1877 }
1878 }
1879 d->must_size++;
1880 if (i != -1) {
1881 /* no match found */
Radek Krejciadb57612016-02-16 13:34:34 +01001882 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child,
1883 d->must[d->must_size - 1].expr, child->name);
1884 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001885 goto error;
1886 }
1887 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001888 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1889 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001890 goto error;
1891 }
1892 (*trg_must_size)++;
1893 }
1894 } else if (!strcmp(child->name, "unique")) {
1895 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001896 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001897 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001898 goto error;
1899 }
1900
1901 /* find unique structures to delete */
1902 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001903 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001904 continue;
1905 }
1906
Radek Krejci581ce772015-11-10 17:22:40 +01001907 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1908 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001909 break;
1910 }
1911 }
1912
Radek Krejci581ce772015-11-10 17:22:40 +01001913 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001914 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001915 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001916 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001917 }
1918 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001919 /* ... and maintain the array */
1920 list->unique_size--;
1921 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001922 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1923 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001924 }
1925
1926 if (!list->unique_size) {
1927 free(list->unique);
1928 list->unique = NULL;
1929 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001930 list->unique[list->unique_size].expr_size = 0;
1931 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001932 }
1933
1934 i = -1; /* set match flag */
1935 break;
1936 }
1937 }
1938
1939 d->unique_size++;
1940 if (i != -1) {
1941 /* no match found */
Radek Krejciadb57612016-02-16 13:34:34 +01001942 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, lyxml_get_attr(child, "tag", NULL), child->name);
1943 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001944 goto error;
1945 }
1946 } else { /* replace or add */
Michal Vasko60f4b452016-02-12 11:02:55 +01001947 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001948 list->unique_size++;
1949 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001950 goto error;
1951 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001952 }
1953 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001954 }
Radek Krejci5b917642015-07-02 09:03:13 +02001955
1956 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 }
1958
Radek Krejcieb00f512015-07-01 16:44:58 +02001959 return EXIT_SUCCESS;
1960
1961error:
1962
Radek Krejcieb00f512015-07-01 16:44:58 +02001963 return EXIT_FAILURE;
1964}
1965
Michal Vasko0d343d12015-08-24 14:57:36 +02001966/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001967static int
Radek Krejcib8048692015-08-05 13:36:34 +02001968fill_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 +02001969 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001970{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001971 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001972 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001973 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001974 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001975
Michal Vasko591e0b22015-08-13 13:53:43 +02001976 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001978 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001979 if (!aug->target_name) {
1980 goto error;
1981 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001983
Michal Vasko1d87a922015-08-21 12:57:16 +02001984 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001985 goto error;
1986 }
1987
1988 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001989 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1990 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001991 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001992 continue;
1993 }
1994
Radek Krejci3cf9e222015-06-18 11:37:50 +02001995 if (!strcmp(child->name, "if-feature")) {
1996 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001998 } else if (!strcmp(child->name, "when")) {
1999 if (aug->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002000 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002001 goto error;
2002 }
2003
2004 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002005 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002006 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002007 goto error;
2008 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002009 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002010 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002011
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 /* check allowed data sub-statements */
2013 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002014 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002015 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002016 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002018 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002019 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002021 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002026 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002027 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002028 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002029 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002030 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002031 goto error;
2032 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002033
Radek Krejci1d82ef62015-08-07 14:44:40 +02002034 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002035 goto error;
2036 }
2037
2038 /* check for mandatory nodes - if the target node is in another module
2039 * the added nodes cannot be mandatory
2040 */
Radek Krejcic6556022016-01-27 15:16:45 +01002041 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002042 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child,
2043 "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002044 goto error;
2045 }
2046
Radek Krejci1d82ef62015-08-07 14:44:40 +02002047 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002048 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002049 }
2050
2051 if (c) {
2052 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002053 if (!aug->features) {
2054 LOGMEM;
2055 goto error;
2056 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002057 }
2058
2059 LY_TREE_FOR_SAFE(yin->child, next, child) {
2060 if (!strcmp(child->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01002061 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002062 aug->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01002063 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002064 goto error;
2065 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002066 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002067 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002068 }
2069
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002070 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002071 * connected to the tree and adjusted (if possible right now).
2072 * However, if this is augment in a uses, it gets resolved
2073 * when the uses does and cannot be resolved now for sure
2074 * (the grouping was not yet copied into uses).
2075 */
2076 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko7178e692016-02-12 15:58:05 +01002077 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin)) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002078 goto error;
2079 }
Michal Vasko49291b32015-08-06 09:49:41 +02002080 }
Radek Krejci106efc02015-06-10 14:36:27 +02002081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002083
2084error:
2085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002087}
2088
Michal Vasko0d343d12015-08-24 14:57:36 +02002089/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090static int
Michal Vasko0d204592015-10-07 09:50:04 +02002091fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002092{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 struct lyxml_elem *sub, *next;
2094 const char *value;
2095 char *endptr;
2096 int f_mand = 0, f_min = 0, f_max = 0;
2097 int c_must = 0;
2098 int r;
2099 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002100
Radek Krejci76512572015-08-04 09:47:08 +02002101 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 goto error;
2103 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002104
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002105 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002106 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002107 if (!rfn->target_name) {
2108 goto error;
2109 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002112 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2113 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002114 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002115 continue;
2116 }
2117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 /* limited applicability */
2119 if (!strcmp(sub->name, "default")) {
2120 /* leaf or choice */
2121 if (rfn->mod.dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01002122 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 goto error;
2124 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 /* check possibility of statements combination */
2127 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002128 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002130 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 goto error;
2132 }
2133 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002134 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 GETVAL(value, sub, "value");
2138 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2139 } else if (!strcmp(sub->name, "mandatory")) {
2140 /* leaf, choice or anyxml */
2141 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002142 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 goto error;
2144 }
2145 /* just checking the flags in leaf is not sufficient, we would allow
2146 * multiple mandatory statements with the "false" value
2147 */
2148 f_mand = 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_LEAF | LYS_CHOICE | LYS_ANYXML);
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_LEAF | LYS_CHOICE | LYS_ANYXML;
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 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002163 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002165 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002167 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 goto error;
2169 }
2170 } else if (!strcmp(sub->name, "min-elements")) {
2171 /* list or leaf-list */
2172 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01002173 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 goto error;
2175 }
2176 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 /* check possibility of statements combination */
2179 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002180 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002182 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 goto error;
2184 }
2185 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002186 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 GETVAL(value, sub, "value");
2190 while (isspace(value[0])) {
2191 value++;
2192 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 /* convert it to uint32_t */
2195 errno = 0;
2196 endptr = NULL;
2197 val = strtoul(value, &endptr, 10);
2198 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01002199 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 goto error;
2201 }
2202 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 /* magic - bit 3 in flags means min set */
2205 rfn->flags |= 0x04;
2206 } else if (!strcmp(sub->name, "max-elements")) {
2207 /* list or leaf-list */
2208 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01002209 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 goto error;
2211 }
2212 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 /* check possibility of statements combination */
2215 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002216 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002218 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 goto error;
2220 }
2221 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002222 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 GETVAL(value, sub, "value");
2226 while (isspace(value[0])) {
2227 value++;
2228 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002229
Radek Krejci0d7b2472016-02-12 11:11:03 +01002230 if (!strcmp(value, "unbounded")) {
2231 rfn->mod.list.max = 0;
2232 } else {
2233 /* convert it to uint32_t */
2234 errno = 0;
2235 endptr = NULL;
2236 val = strtoul(value, &endptr, 10);
2237 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01002238 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002239 goto error;
2240 }
2241 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 /* magic - bit 4 in flags means min set */
2245 rfn->flags |= 0x08;
2246 } else if (!strcmp(sub->name, "presence")) {
2247 /* container */
2248 if (rfn->mod.presence) {
Radek Krejciadb57612016-02-16 13:34:34 +01002249 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 goto error;
2251 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 /* check possibility of statements combination */
2254 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002255 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002257 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 goto error;
2259 }
2260 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002261 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 GETVAL(value, sub, "value");
2265 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2266 } else if (!strcmp(sub->name, "must")) {
2267 /* leaf-list, list, container or anyxml */
2268 /* check possibility of statements combination */
2269 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002270 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002272 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 goto error;
2274 }
2275 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002276 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002280 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002283 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002284 goto error;
2285 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002286
Michal Vasko345da0a2015-12-02 10:35:55 +01002287 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 /* process nodes with cardinality of 0..n */
2291 if (c_must) {
2292 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002293 if (!rfn->must) {
2294 LOGMEM;
2295 goto error;
2296 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 }
Radek Krejci73adb602015-07-02 18:07:40 +02002298 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002299 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2300 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002301 if (r) {
2302 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002307
2308error:
2309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002311}
2312
Michal Vasko0d343d12015-08-24 14:57:36 +02002313/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314static int
Radek Krejcib8048692015-08-05 13:36:34 +02002315fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002316{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 struct lyxml_elem *child;
2318 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002319 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002322 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2323 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002324 continue;
2325 }
2326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 if (!strcmp(child->name, "prefix")) {
2328 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002329 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002330 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 goto error;
2332 }
2333 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2334 } else if (!strcmp(child->name, "revision-date")) {
2335 if (imp->rev[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +01002336 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 goto error;
2338 }
2339 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002340 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01002341 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 goto error;
2343 }
2344 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2345 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002346 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 goto error;
2348 }
2349 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 /* check mandatory information */
2352 if (!imp->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01002353 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 goto error;
2355 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002358
2359 /* check for circular import, store it if passed */
2360 if (!module->ctx->models.parsing) {
2361 count = 0;
2362 } else {
2363 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2364 if (value == module->ctx->models.parsing[count]) {
2365 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2366 goto error;
2367 }
2368 }
2369 }
2370 ++count;
2371 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002372 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2373 if (!module->ctx->models.parsing) {
2374 LOGMEM;
2375 goto error;
2376 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002377 module->ctx->models.parsing[count - 1] = value;
2378 module->ctx->models.parsing[count] = NULL;
2379
2380 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002381 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 +02002382 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002383 /* whether to use a user callback is decided in the function */
2384 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 +02002385 }
2386
2387 /* remove the new module name now that its parsing is finished (even if failed) */
2388 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2389 LOGINT;
2390 }
2391 --count;
2392 if (count) {
2393 module->ctx->models.parsing[count] = NULL;
2394 } else {
2395 free(module->ctx->models.parsing);
2396 module->ctx->models.parsing = NULL;
2397 }
2398
2399 /* check the result */
2400 if (!imp->module) {
Radek Krejciadb57612016-02-16 13:34:34 +01002401 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002402 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2403 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002407
2408error:
2409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002411}
2412
Michal Vasko0d343d12015-08-24 14:57:36 +02002413/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002414static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002415fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2416 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002417{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 struct lyxml_elem *child;
2419 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002420 char *module_data;
2421 void (*module_data_free)(char *module_data) = NULL;
2422 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko5a721fd2016-02-16 12:16:48 +01002423 int count, i;
Radek Krejciefaeba32015-05-27 14:30:57 +02002424
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002426 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2427 /* garbage */
2428 continue;
2429 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002430 if (!strcmp(child->name, "revision-date")) {
2431 if (inc->rev[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +01002432 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 goto error;
2434 }
2435 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002436 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01002437 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 goto error;
2439 }
2440 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2441 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002442 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002443 goto error;
2444 }
2445 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002447 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002448
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002449 /* check that the submodule was not included yet (previous submodule could have included it) */
2450 for (i = 0; i < module->inc_size; ++i) {
2451 if (module->inc[i].submodule && (module->inc[i].submodule->name == value)) {
Michal Vasko5ff78822016-02-12 09:33:31 +01002452 /* copy the duplicate into the result */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002453 memcpy(inc, &module->inc[i], sizeof *inc);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002454
Michal Vasko5ff78822016-02-12 09:33:31 +01002455 if (submodule) {
2456 /* we don't care if it was external or not */
2457 inc->external = 0;
2458 } else if (inc->external) {
2459 /* remove the duplicate */
2460 --module->inc_size;
2461 memmove(&module->inc[i], &module->inc[i + 1], (module->inc_size - i) * sizeof *inc);
2462 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
2463
2464 /* it is no longer external */
2465 inc->external = 0;
2466 }
2467 /* if !submodule && !inc->external, we just create a duplicate so it is detected and ended with error */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002468
2469 return EXIT_SUCCESS;
2470 }
2471 }
2472
Michal Vasko1b882eb2015-10-22 11:43:14 +02002473 /* check for circular include, store it if passed */
2474 if (!module->ctx->models.parsing) {
2475 count = 0;
2476 } else {
2477 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2478 if (value == module->ctx->models.parsing[count]) {
2479 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2480 goto error;
2481 }
2482 }
2483 }
2484 ++count;
2485 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002486 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2487 if (!module->ctx->models.parsing) {
2488 LOGMEM;
2489 goto error;
2490 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002491 module->ctx->models.parsing[count - 1] = value;
2492 module->ctx->models.parsing[count] = NULL;
2493
2494 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002495 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002497 if (module->ctx->module_clb) {
2498 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2499 &format, &module_data_free);
2500 if (module_data) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01002501 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002502 if (module_data_free) {
2503 module_data_free(module_data);
2504 } else {
2505 free(module_data);
2506 }
2507 } else {
2508 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2509 }
2510 } else {
Michal Vasko5a721fd2016-02-16 12:16:48 +01002511 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
2512 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002513 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002514 }
2515
2516 /* remove the new submodule name now that its parsing is finished (even if failed) */
2517 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2518 LOGINT;
2519 }
2520 --count;
2521 if (count) {
2522 module->ctx->models.parsing[count] = NULL;
2523 } else {
2524 free(module->ctx->models.parsing);
2525 module->ctx->models.parsing = NULL;
2526 }
2527
2528 /* check the result */
Michal Vasko5a721fd2016-02-16 12:16:48 +01002529 if (!inc->submodule) {
Radek Krejciadb57612016-02-16 13:34:34 +01002530 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002531 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2532 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002536
2537error:
2538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002540}
2541
Michal Vasko0d343d12015-08-24 14:57:36 +02002542/* logs directly
2543 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002544 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002545 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002546 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002547 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548static int
Radek Krejcib8048692015-08-05 13:36:34 +02002549read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002550 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002551{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 const char *value;
2553 struct lyxml_elem *sub, *next;
2554 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002557 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002558 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 if (opt & OPT_IDENT) {
2561 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002562 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002563 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, xmlnode);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 goto error;
2565 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002566 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002568
Radek Krejci6764bb32015-07-03 15:16:04 +02002569 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002570 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002571 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002572 }
2573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002574 /* process local parameters */
2575 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002576 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002577 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002578 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002579 continue;
2580 }
2581 if (strcmp(sub->ns->value, LY_NSYIN)) {
2582 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002583 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002584 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002585 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002586 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002587 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002588 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002589 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002590 goto error;
2591 }
2592 }
2593
2594 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002595 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002596 continue;
2597 }
2598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002599 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002600 if (node->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01002601 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 goto error;
2603 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002604 node->dsc = read_yin_subnode(ctx, sub, "text");
2605 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002606 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 }
2608 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002609 if (node->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01002610 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 goto error;
2612 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002613 node->ref = read_yin_subnode(ctx, sub, "text");
2614 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002615 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002616 }
2617 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002618 if (node->flags & LYS_STATUS_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01002619 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002620 goto error;
2621 }
2622 GETVAL(value, sub, "value");
2623 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002624 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002626 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002628 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002629 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002630 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002631 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002632 }
2633 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002634 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01002635 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 goto error;
2637 }
2638 GETVAL(value, sub, "value");
2639 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002640 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002641 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002642 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002644 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002645 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 }
2647 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002648 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 continue;
2650 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002651 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002652 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002653
Radek Krejci1d82ef62015-08-07 14:44:40 +02002654 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002655 /* get config flag from parent */
2656 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002657 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 } else {
2659 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002660 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002661 }
2662 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002664 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002665
2666error:
2667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002668 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002669}
2670
Michal Vasko0d343d12015-08-24 14:57:36 +02002671/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002672static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002673read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002674{
Radek Krejci76512572015-08-04 09:47:08 +02002675 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002676 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002677 const char *value;
2678
2679 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002680 if (!retval) {
2681 LOGMEM;
2682 return NULL;
2683 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002684
2685 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002686 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002687 if (!retval->cond) {
2688 goto error;
2689 }
Michal Vasko27f2da82016-02-15 12:32:42 +01002690 if (lyxp_syntax_check(retval->cond, LOGLINE(yin))) {
2691 goto error;
2692 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002693
Radek Krejci73adb602015-07-02 18:07:40 +02002694 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002695 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2696 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002697 continue;
2698 }
2699
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002700 if (!strcmp(child->name, "description")) {
2701 if (retval->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01002702 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002703 goto error;
2704 }
2705 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2706 if (!retval->dsc) {
2707 goto error;
2708 }
2709 } else if (!strcmp(child->name, "reference")) {
2710 if (retval->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01002711 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002712 goto error;
2713 }
2714 retval->ref = read_yin_subnode(module->ctx, child, "text");
2715 if (!retval->ref) {
2716 goto error;
2717 }
2718 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002719 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002720 goto error;
2721 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002722 }
2723
2724 return retval;
2725
2726error:
2727
Michal Vasko0308dd62015-10-07 09:14:40 +02002728 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002729 return NULL;
2730}
2731
Michal Vasko0d343d12015-08-24 14:57:36 +02002732/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002733static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002734read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2735 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002736{
Michal Vasko29fc0182015-08-24 15:02:39 +02002737 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002738 struct lys_node_case *cs;
2739 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002740 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002741
Radek Krejcie867c852015-08-27 09:52:34 +02002742 /* init */
2743 memset(&root, 0, sizeof root);
2744
Radek Krejci1d82ef62015-08-07 14:44:40 +02002745 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002746 if (!cs) {
2747 LOGMEM;
2748 return NULL;
2749 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002750 cs->nodetype = LYS_CASE;
2751 cs->prev = (struct lys_node *)cs;
2752 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002753
Radek Krejci6a113852015-07-03 16:04:20 +02002754 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002755 goto error;
2756 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002757
Radek Krejcia9544502015-08-14 08:24:29 +02002758 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2759
Michal Vasko3a0043f2015-08-12 12:11:30 +02002760 /* insert the node into the schema tree */
Michal Vasko6c629ac2016-02-15 14:08:23 +01002761 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002762 goto error;
2763 }
2764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 /* process choice's specific children */
2766 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002767 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2768 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002769 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002770 continue;
2771 }
2772
Michal Vasko29fc0182015-08-24 15:02:39 +02002773 if (!strcmp(sub->name, "container") ||
2774 !strcmp(sub->name, "leaf-list") ||
2775 !strcmp(sub->name, "leaf") ||
2776 !strcmp(sub->name, "list") ||
2777 !strcmp(sub->name, "uses") ||
2778 !strcmp(sub->name, "choice") ||
2779 !strcmp(sub->name, "anyxml")) {
2780
Michal Vaskof3930de2015-10-22 12:03:59 +02002781 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002782 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002783 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002784 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002785 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002786 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002787 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002788 if (cs->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002789 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002790 goto error;
2791 }
2792
Radek Krejci1d82ef62015-08-07 14:44:40 +02002793 cs->when = read_yin_when(module, sub);
2794 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002795 goto error;
2796 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002797
Michal Vasko345da0a2015-12-02 10:35:55 +01002798 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002800 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002804
Radek Krejci3cf9e222015-06-18 11:37:50 +02002805 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002806 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002807 if (!cs->features) {
2808 LOGMEM;
2809 goto error;
2810 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002811 }
Radek Krejci73adb602015-07-02 18:07:40 +02002812 LY_TREE_FOR(yin->child, sub) {
Michal Vasko217db072016-02-15 12:32:04 +01002813 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002814 cs->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01002815 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002816 goto error;
2817 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 }
Radek Krejcib388c152015-06-04 17:03:03 +02002819
Michal Vasko29fc0182015-08-24 15:02:39 +02002820 /* last part - process data nodes */
2821 LY_TREE_FOR_SAFE(root.child, next, sub) {
2822 if (!strcmp(sub->name, "container")) {
2823 node = read_yin_container(module, retval, sub, resolve, unres);
2824 } else if (!strcmp(sub->name, "leaf-list")) {
2825 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2826 } else if (!strcmp(sub->name, "leaf")) {
2827 node = read_yin_leaf(module, retval, sub, resolve, unres);
2828 } else if (!strcmp(sub->name, "list")) {
2829 node = read_yin_list(module, retval, sub, resolve, unres);
2830 } else if (!strcmp(sub->name, "choice")) {
2831 node = read_yin_choice(module, retval, sub, resolve, unres);
2832 } else if (!strcmp(sub->name, "uses")) {
2833 node = read_yin_uses(module, retval, sub, resolve, unres);
2834 } else if (!strcmp(sub->name, "anyxml")) {
2835 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2836 }
2837 if (!node) {
2838 goto error;
2839 }
2840
Michal Vasko345da0a2015-12-02 10:35:55 +01002841 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002842 }
2843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002845
2846error:
2847
Michal Vasko29fc0182015-08-24 15:02:39 +02002848 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002849 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002850 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002851 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002854}
2855
Michal Vasko0d343d12015-08-24 14:57:36 +02002856/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002857static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002858read_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 +02002859{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860 struct lyxml_elem *sub, *next;
2861 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002862 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002863 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002864 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002865 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002867 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002868 if (!choice) {
2869 LOGMEM;
2870 return NULL;
2871 }
Radek Krejci76512572015-08-04 09:47:08 +02002872 choice->nodetype = LYS_CHOICE;
2873 choice->prev = (struct lys_node *)choice;
2874 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002875
Michal Vaskoe0c59842015-09-24 13:52:20 +02002876 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2877 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 goto error;
2879 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002880
Radek Krejcia9544502015-08-14 08:24:29 +02002881 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2882
Michal Vasko3a0043f2015-08-12 12:11:30 +02002883 /* insert the node into the schema tree */
Michal Vasko6c629ac2016-02-15 14:08:23 +01002884 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002885 goto error;
2886 }
2887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 /* process choice's specific children */
2889 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002890 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2891 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002892 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002893 continue;
2894 }
2895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002896 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002897 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002898 goto error;
2899 }
2900 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002901 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 goto error;
2903 }
2904 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002905 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 goto error;
2907 }
2908 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002909 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 goto error;
2911 }
2912 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002913 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 goto error;
2915 }
2916 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002917 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002918 goto error;
2919 }
2920 } else if (!strcmp(sub->name, "default")) {
2921 if (dflt_str) {
Radek Krejciadb57612016-02-16 13:34:34 +01002922 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 goto error;
2924 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002925 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 } else if (!strcmp(sub->name, "mandatory")) {
2927 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002928 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 goto error;
2930 }
2931 /* just checking the flags in leaf is not sufficient, we would allow
2932 * multiple mandatory statements with the "false" value
2933 */
2934 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 GETVAL(value, sub, "value");
2937 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002938 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002939 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002940 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002941 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002942 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 goto error;
2944 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002945 } else if (!strcmp(sub->name, "when")) {
2946 if (choice->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002947 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002948 goto error;
2949 }
2950
2951 choice->when = read_yin_when(module, sub);
2952 if (!choice->when) {
2953 goto error;
2954 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002955 } else if (!strcmp(sub->name, "if-feature")) {
2956 c_ftrs++;
2957
Michal Vasko345da0a2015-12-02 10:35:55 +01002958 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002959 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002960 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002961 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002962 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002964
Radek Krejci1d82ef62015-08-07 14:44:40 +02002965 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002966 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002968
Radek Krejci3cf9e222015-06-18 11:37:50 +02002969 if (c_ftrs) {
2970 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002971 if (!choice->features) {
2972 LOGMEM;
2973 goto error;
2974 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002975 }
2976
Radek Krejci73adb602015-07-02 18:07:40 +02002977 LY_TREE_FOR(yin->child, sub) {
Michal Vasko217db072016-02-15 12:32:04 +01002978 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002979 choice->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01002980 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002981 goto error;
2982 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002983 }
2984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002986 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002987 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2989 goto error;
2990 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 /* link default with the case */
2993 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002994 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002995 goto error;
2996 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003000
3001error:
3002
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003003 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003005 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003006}
3007
Michal Vasko0d343d12015-08-24 14:57:36 +02003008/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003009static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003010read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003011 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003012{
Radek Krejci76512572015-08-04 09:47:08 +02003013 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003014 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003015 struct lyxml_elem *sub, *next;
3016 const char *value;
3017 int r;
3018 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003019 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003022 if (!anyxml) {
3023 LOGMEM;
3024 return NULL;
3025 }
Radek Krejci76512572015-08-04 09:47:08 +02003026 anyxml->nodetype = LYS_ANYXML;
3027 anyxml->prev = (struct lys_node *)anyxml;
3028 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003029
Michal Vaskoe0c59842015-09-24 13:52:20 +02003030 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3031 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 goto error;
3033 }
Radek Krejci863c2852015-06-03 15:47:11 +02003034
Radek Krejcia9544502015-08-14 08:24:29 +02003035 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003036
Michal Vasko6c629ac2016-02-15 14:08:23 +01003037 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003038 goto error;
3039 }
3040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003042 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3043 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003044 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003045 continue;
3046 }
3047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 if (!strcmp(sub->name, "mandatory")) {
3049 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01003050 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 goto error;
3052 }
3053 /* just checking the flags in leaf is not sufficient, we would allow
3054 * multiple mandatory statements with the "false" value
3055 */
3056 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 GETVAL(value, sub, "value");
3059 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003060 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003061 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003062 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003063 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003064 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 goto error;
3066 }
3067 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003068 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003069 } else if (!strcmp(sub->name, "when")) {
3070 if (anyxml->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003071 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003072 goto error;
3073 }
3074
3075 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003076 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003077 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003078 goto error;
3079 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003080 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 } else if (!strcmp(sub->name, "must")) {
3082 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003083 } else if (!strcmp(sub->name, "if-feature")) {
3084 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003087 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 }
3090 }
Radek Krejci863c2852015-06-03 15:47:11 +02003091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 /* middle part - process nodes with cardinality of 0..n */
3093 if (c_must) {
3094 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003095 if (!anyxml->must) {
3096 LOGMEM;
3097 goto error;
3098 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003100 if (c_ftrs) {
3101 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003102 if (!anyxml->features) {
3103 LOGMEM;
3104 goto error;
3105 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003106 }
Radek Krejci863c2852015-06-03 15:47:11 +02003107
Radek Krejci73adb602015-07-02 18:07:40 +02003108 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003109 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003110 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3111 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003112 if (r) {
3113 goto error;
3114 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003115 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003116 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003117 anyxml->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003118 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003119 goto error;
3120 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 }
Radek Krejci863c2852015-06-03 15:47:11 +02003123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003125
3126error:
3127
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003128 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003131}
3132
Michal Vasko0d343d12015-08-24 14:57:36 +02003133/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003134static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003135read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003136 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003137{
Radek Krejci76512572015-08-04 09:47:08 +02003138 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003139 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 struct lyxml_elem *sub, *next;
3141 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003142 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003143 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003146 if (!leaf) {
3147 LOGMEM;
3148 return NULL;
3149 }
Radek Krejci76512572015-08-04 09:47:08 +02003150 leaf->nodetype = LYS_LEAF;
3151 leaf->prev = (struct lys_node *)leaf;
3152 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003153
Michal Vaskoe0c59842015-09-24 13:52:20 +02003154 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3155 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 goto error;
3157 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003158
Radek Krejcia9544502015-08-14 08:24:29 +02003159 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003160
Michal Vasko6c629ac2016-02-15 14:08:23 +01003161 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003162 goto error;
3163 }
3164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003166 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3167 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003168 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003169 continue;
3170 }
3171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003173 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003174 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 goto error;
3176 }
Michal Vasko88c29542015-11-27 14:57:53 +01003177 /* HACK for unres */
3178 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003179 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003180 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3181 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 goto error;
3183 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003184 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 } else if (!strcmp(sub->name, "default")) {
3186 if (leaf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01003187 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 goto error;
3189 }
3190 GETVAL(value, sub, "value");
3191 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003192 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 } else if (!strcmp(sub->name, "units")) {
3194 if (leaf->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01003195 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003196 goto error;
3197 }
3198 GETVAL(value, sub, "name");
3199 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3200 } else if (!strcmp(sub->name, "mandatory")) {
3201 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01003202 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 goto error;
3204 }
3205 /* just checking the flags in leaf is not sufficient, we would allow
3206 * multiple mandatory statements with the "false" value
3207 */
3208 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 GETVAL(value, sub, "value");
3211 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003212 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003213 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003214 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003215 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003216 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003217 goto error;
3218 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003219 } else if (!strcmp(sub->name, "when")) {
3220 if (leaf->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003221 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003222 goto error;
3223 }
3224
3225 leaf->when = read_yin_when(module, sub);
3226 if (!leaf->when) {
3227 goto error;
3228 }
3229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003231 c_must++;
3232 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003233 } else if (!strcmp(sub->name, "if-feature")) {
3234 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003238 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003241
Michal Vasko88c29542015-11-27 14:57:53 +01003242 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003246 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003247 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003248 goto error;
3249 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003250 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003251 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003252 goto error;
3253 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 /* middle part - process nodes with cardinality of 0..n */
3257 if (c_must) {
3258 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003259 if (!leaf->must) {
3260 LOGMEM;
3261 goto error;
3262 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003264 if (c_ftrs) {
3265 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003266 if (!leaf->features) {
3267 LOGMEM;
3268 goto error;
3269 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003270 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003271
Radek Krejci73adb602015-07-02 18:07:40 +02003272 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003274 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3275 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003276 if (r) {
3277 goto error;
3278 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003279 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003280 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003281 leaf->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003282 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003283 goto error;
3284 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003289
3290error:
3291
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003292 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003295}
3296
Michal Vasko0d343d12015-08-24 14:57:36 +02003297/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003298static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003299read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003300 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003301{
Radek Krejci76512572015-08-04 09:47:08 +02003302 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003303 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 struct lyxml_elem *sub, *next;
3305 const char *value;
3306 char *endptr;
3307 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003308 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003309 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003313 if (!llist) {
3314 LOGMEM;
3315 return NULL;
3316 }
Radek Krejci76512572015-08-04 09:47:08 +02003317 llist->nodetype = LYS_LEAFLIST;
3318 llist->prev = (struct lys_node *)llist;
3319 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003320
Michal Vaskoe0c59842015-09-24 13:52:20 +02003321 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3322 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 goto error;
3324 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003325
Radek Krejcia9544502015-08-14 08:24:29 +02003326 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003327
Michal Vasko6c629ac2016-02-15 14:08:23 +01003328 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003329 goto error;
3330 }
3331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003333 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3334 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003335 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003336 continue;
3337 }
3338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003340 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003341 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 goto error;
3343 }
Michal Vasko88c29542015-11-27 14:57:53 +01003344 /* HACK for unres */
3345 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003346 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003347 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3348 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 goto error;
3350 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003351 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 } else if (!strcmp(sub->name, "units")) {
3353 if (llist->units) {
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 GETVAL(value, sub, "name");
3358 llist->units = lydict_insert(module->ctx, value, strlen(value));
3359 } else if (!strcmp(sub->name, "ordered-by")) {
3360 if (f_ordr) {
Radek Krejciadb57612016-02-16 13:34:34 +01003361 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 goto error;
3363 }
3364 /* just checking the flags in llist is not sufficient, we would
3365 * allow multiple ordered-by statements with the "system" value
3366 */
3367 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003368
Radek Krejci1574a8d2015-08-03 14:16:52 +02003369 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003370 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3371 * state data
3372 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003373 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003374 continue;
3375 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003377 GETVAL(value, sub, "value");
3378 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003379 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 } else if (strcmp(value, "system")) {
Radek Krejciadb57612016-02-16 13:34:34 +01003381 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003383 } /* else system is the default value, so we can ignore it */
3384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 } else if (!strcmp(sub->name, "must")) {
3386 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003387 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003388 } else if (!strcmp(sub->name, "if-feature")) {
3389 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003392 } else if (!strcmp(sub->name, "min-elements")) {
3393 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01003394 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 goto error;
3396 }
3397 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 GETVAL(value, sub, "value");
3400 while (isspace(value[0])) {
3401 value++;
3402 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 /* convert it to uint32_t */
3405 errno = 0;
3406 endptr = NULL;
3407 val = strtoul(value, &endptr, 10);
3408 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003409 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 goto error;
3411 }
3412 llist->min = (uint32_t) val;
3413 } else if (!strcmp(sub->name, "max-elements")) {
3414 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003415 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 goto error;
3417 }
3418 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 GETVAL(value, sub, "value");
3421 while (isspace(value[0])) {
3422 value++;
3423 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003424
Radek Krejci0d7b2472016-02-12 11:11:03 +01003425 if (!strcmp(value, "unbounded")) {
3426 llist->max = 0;
3427 } else {
3428 /* convert it to uint32_t */
3429 errno = 0;
3430 endptr = NULL;
3431 val = strtoul(value, &endptr, 10);
3432 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003433 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003434 goto error;
3435 }
3436 llist->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003438 } else if (!strcmp(sub->name, "when")) {
3439 if (llist->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003440 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003441 goto error;
3442 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003443
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003444 llist->when = read_yin_when(module, sub);
3445 if (!llist->when) {
3446 goto error;
3447 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003449 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003452
Michal Vasko88c29542015-11-27 14:57:53 +01003453 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003457 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003458 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 goto error;
3460 }
3461 if (llist->max && llist->min > llist->max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003462 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 goto error;
3464 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 /* middle part - process nodes with cardinality of 0..n */
3467 if (c_must) {
3468 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003469 if (!llist->must) {
3470 LOGMEM;
3471 goto error;
3472 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003474 if (c_ftrs) {
3475 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003476 if (!llist->features) {
3477 LOGMEM;
3478 goto error;
3479 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003480 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003481
Radek Krejci73adb602015-07-02 18:07:40 +02003482 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003484 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3485 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 if (r) {
3487 goto error;
3488 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003489 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003490 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003491 llist->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003492 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003493 goto error;
3494 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003499
3500error:
3501
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003502 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003505}
3506
Michal Vasko0d343d12015-08-24 14:57:36 +02003507/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003508static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003509read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3510 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003511{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003512 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003513 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003515 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003516 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003518 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003519 char *auxs;
3520 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003522 /* init */
3523 memset(&root, 0, sizeof root);
3524 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003527 if (!list) {
3528 LOGMEM;
3529 return NULL;
3530 }
Radek Krejci76512572015-08-04 09:47:08 +02003531 list->nodetype = LYS_LIST;
3532 list->prev = (struct lys_node *)list;
3533 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003534
Michal Vaskoe0c59842015-09-24 13:52:20 +02003535 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3536 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 goto error;
3538 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003539
Radek Krejcia9544502015-08-14 08:24:29 +02003540 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 /* process list's specific children */
3543 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003544 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3545 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003546 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003547 continue;
3548 }
3549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 /* data statements */
3551 if (!strcmp(sub->name, "container") ||
3552 !strcmp(sub->name, "leaf-list") ||
3553 !strcmp(sub->name, "leaf") ||
3554 !strcmp(sub->name, "list") ||
3555 !strcmp(sub->name, "choice") ||
3556 !strcmp(sub->name, "uses") ||
3557 !strcmp(sub->name, "grouping") ||
3558 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003559 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003560 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 /* array counters */
3563 } else if (!strcmp(sub->name, "key")) {
3564 /* check cardinality 0..1 */
3565 if (list->keys_size) {
Radek Krejciadb57612016-02-16 13:34:34 +01003566 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 goto error;
3568 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 /* count the number of keys */
3571 GETVAL(value, sub, "value");
3572 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003573 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 while ((value = strpbrk(value, " \t\n"))) {
3575 list->keys_size++;
3576 while (isspace(*value)) {
3577 value++;
3578 }
3579 }
3580 list->keys_size++;
3581 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003582 if (!list->keys) {
3583 LOGMEM;
3584 goto error;
3585 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 } else if (!strcmp(sub->name, "unique")) {
3587 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003588 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003589 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 } else if (!strcmp(sub->name, "typedef")) {
3591 c_tpdf++;
3592 } else if (!strcmp(sub->name, "must")) {
3593 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003594 } else if (!strcmp(sub->name, "if-feature")) {
3595 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 /* optional stetments */
3598 } else if (!strcmp(sub->name, "ordered-by")) {
3599 if (f_ordr) {
Radek Krejciadb57612016-02-16 13:34:34 +01003600 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 goto error;
3602 }
3603 /* just checking the flags in llist is not sufficient, we would
3604 * allow multiple ordered-by statements with the "system" value
3605 */
3606 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003607
Radek Krejci1574a8d2015-08-03 14:16:52 +02003608 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3610 * state data
3611 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003612 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 continue;
3614 }
Radek Krejci345ad742015-06-03 11:04:18 +02003615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 GETVAL(value, sub, "value");
3617 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003618 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 } else if (strcmp(value, "system")) {
Radek Krejciadb57612016-02-16 13:34:34 +01003620 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 goto error;
3622 }
3623 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003624 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 } else if (!strcmp(sub->name, "min-elements")) {
3626 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01003627 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 goto error;
3629 }
3630 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 GETVAL(value, sub, "value");
3633 while (isspace(value[0])) {
3634 value++;
3635 }
Radek Krejci345ad742015-06-03 11:04:18 +02003636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 /* convert it to uint32_t */
3638 errno = 0;
3639 auxs = NULL;
3640 val = strtoul(value, &auxs, 10);
3641 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003642 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 goto error;
3644 }
3645 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003646 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 } else if (!strcmp(sub->name, "max-elements")) {
3648 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003649 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 goto error;
3651 }
3652 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 GETVAL(value, sub, "value");
3655 while (isspace(value[0])) {
3656 value++;
3657 }
Radek Krejci345ad742015-06-03 11:04:18 +02003658
Radek Krejci0d7b2472016-02-12 11:11:03 +01003659 if (!strcmp(value, "unbounded")) {
3660 list->max = 0;;
3661 } else {
3662 /* convert it to uint32_t */
3663 errno = 0;
3664 auxs = NULL;
3665 val = strtoul(value, &auxs, 10);
3666 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003667 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003668 goto error;
3669 }
3670 list->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003672 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003673 } else if (!strcmp(sub->name, "when")) {
3674 if (list->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003675 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003676 goto error;
3677 }
3678
3679 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003680 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003681 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003682 goto error;
3683 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003684 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003685 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003686 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003687 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 }
3689 }
Radek Krejci345ad742015-06-03 11:04:18 +02003690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003692 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejciadb57612016-02-16 13:34:34 +01003693 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 goto error;
3695 }
3696 if (list->max && list->min > list->max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003697 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 goto error;
3699 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3702 if (c_tpdf) {
3703 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003704 if (!list->tpdf) {
3705 LOGMEM;
3706 goto error;
3707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003709 if (c_must) {
3710 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003711 if (!list->must) {
3712 LOGMEM;
3713 goto error;
3714 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003715 }
3716 if (c_ftrs) {
3717 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003718 if (!list->features) {
3719 LOGMEM;
3720 goto error;
3721 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003722 }
Radek Krejci73adb602015-07-02 18:07:40 +02003723 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003725 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3726 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 if (r) {
3728 goto error;
3729 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003730 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003731 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003732 list->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003733 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003734 goto error;
3735 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003736 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003737 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3738 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003739 if (r) {
3740 goto error;
3741 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
3743 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003744
Michal Vasko6c629ac2016-02-15 14:08:23 +01003745 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003746 goto error;
3747 }
3748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 /* last part - process data nodes */
3750 LY_TREE_FOR_SAFE(root.child, next, sub) {
3751 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003752 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003754 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003756 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003758 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003760 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003762 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003764 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003766 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003767 } else {
3768 LOGINT;
3769 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003771 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
3773 }
Radek Krejci73adb602015-07-02 18:07:40 +02003774
Michal Vasko345da0a2015-12-02 10:35:55 +01003775 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003777
Radek Krejci461efb92016-02-12 15:52:18 +01003778 if (key_str) {
3779 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
3780 goto error;
3781 }
3782 } /* 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 +02003783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 /* process unique statements */
3785 if (c_uniq) {
3786 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003787 if (!list->unique) {
3788 LOGMEM;
3789 goto error;
3790 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003791
Radek Krejci461efb92016-02-12 15:52:18 +01003792 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3793 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3794 list->unique_size++;
3795 if (r) {
3796 goto error;
3797 }
3798
3799 lyxml_free(module->ctx, sub);
3800 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003804
3805error:
3806
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003807 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003809 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 }
3811 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003812 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003816}
3817
Michal Vasko0d343d12015-08-24 14:57:36 +02003818/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003819static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003820read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3821 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003822{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003823 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003824 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003825 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003826 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 const char *value;
3828 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003829 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 /* init */
3832 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003835 if (!cont) {
3836 LOGMEM;
3837 return NULL;
3838 }
Radek Krejci76512572015-08-04 09:47:08 +02003839 cont->nodetype = LYS_CONTAINER;
3840 cont->prev = (struct lys_node *)cont;
3841 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003842
Michal Vaskoe0c59842015-09-24 13:52:20 +02003843 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3844 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 goto error;
3846 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003847
Radek Krejcia9544502015-08-14 08:24:29 +02003848 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 /* process container's specific children */
3851 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003852 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003853 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003854 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003855 continue;
3856 }
3857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 if (!strcmp(sub->name, "presence")) {
3859 if (cont->presence) {
Radek Krejciadb57612016-02-16 13:34:34 +01003860 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 goto error;
3862 }
3863 GETVAL(value, sub, "value");
3864 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003865
Michal Vasko345da0a2015-12-02 10:35:55 +01003866 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003867 } else if (!strcmp(sub->name, "when")) {
3868 if (cont->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003869 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003870 goto error;
3871 }
3872
3873 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003874 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003875 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003876 goto error;
3877 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003878 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 /* data statements */
3881 } else if (!strcmp(sub->name, "container") ||
3882 !strcmp(sub->name, "leaf-list") ||
3883 !strcmp(sub->name, "leaf") ||
3884 !strcmp(sub->name, "list") ||
3885 !strcmp(sub->name, "choice") ||
3886 !strcmp(sub->name, "uses") ||
3887 !strcmp(sub->name, "grouping") ||
3888 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003889 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003890 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 /* array counters */
3893 } else if (!strcmp(sub->name, "typedef")) {
3894 c_tpdf++;
3895 } else if (!strcmp(sub->name, "must")) {
3896 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003897 } else if (!strcmp(sub->name, "if-feature")) {
3898 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003900 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 }
3903 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3906 if (c_tpdf) {
3907 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003908 if (!cont->tpdf) {
3909 LOGMEM;
3910 goto error;
3911 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 }
3913 if (c_must) {
3914 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003915 if (!cont->must) {
3916 LOGMEM;
3917 goto error;
3918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003920 if (c_ftrs) {
3921 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003922 if (!cont->features) {
3923 LOGMEM;
3924 goto error;
3925 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003926 }
Radek Krejci800af702015-06-02 13:46:01 +02003927
Radek Krejci73adb602015-07-02 18:07:40 +02003928 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003930 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3931 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 if (r) {
3933 goto error;
3934 }
3935 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003936 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3937 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 if (r) {
3939 goto error;
3940 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003941 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003942 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003943 cont->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003944 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003945 goto error;
3946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003949
Michal Vasko6c629ac2016-02-15 14:08:23 +01003950 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003951 goto error;
3952 }
3953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003954 /* last part - process data nodes */
3955 LY_TREE_FOR_SAFE(root.child, next, sub) {
3956 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003957 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003963 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003967 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003969 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003970 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003971 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003972 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003973 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003974 goto error;
3975 }
Radek Krejci73adb602015-07-02 18:07:40 +02003976
Michal Vasko345da0a2015-12-02 10:35:55 +01003977 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003978 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003981
3982error:
3983
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003984 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003986 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003987 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003990}
3991
Michal Vasko0d343d12015-08-24 14:57:36 +02003992/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003993static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003994read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003995 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003996{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003997 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003998 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003999 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004000 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 int r;
4002 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 /* init */
4005 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004007 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004008 if (!grp) {
4009 LOGMEM;
4010 return NULL;
4011 }
Radek Krejci76512572015-08-04 09:47:08 +02004012 grp->nodetype = LYS_GROUPING;
4013 grp->prev = (struct lys_node *)grp;
4014 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004015
Michal Vasko71e1aa82015-08-12 12:17:51 +02004016 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 goto error;
4018 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004019
Radek Krejcia9544502015-08-14 08:24:29 +02004020 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4021
Radek Krejci1d82ef62015-08-07 14:44:40 +02004022 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004023 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4024 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004025 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004026 continue;
4027 }
4028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004029 /* data statements */
4030 if (!strcmp(sub->name, "container") ||
4031 !strcmp(sub->name, "leaf-list") ||
4032 !strcmp(sub->name, "leaf") ||
4033 !strcmp(sub->name, "list") ||
4034 !strcmp(sub->name, "choice") ||
4035 !strcmp(sub->name, "uses") ||
4036 !strcmp(sub->name, "grouping") ||
4037 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004038 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004039 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 /* array counters */
4042 } else if (!strcmp(sub->name, "typedef")) {
4043 c_tpdf++;
4044 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004045 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004046 goto error;
4047 }
4048 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4051 if (c_tpdf) {
4052 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004053 if (!grp->tpdf) {
4054 LOGMEM;
4055 goto error;
4056 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004057 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004058 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004059 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4060 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004061 if (r) {
4062 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004063 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004065
Michal Vasko6c629ac2016-02-15 14:08:23 +01004066 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004067 goto error;
4068 }
4069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004070 /* last part - process data nodes */
4071 LY_TREE_FOR_SAFE(root.child, next, sub) {
4072 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004073 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004074 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004075 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004076 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004077 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004078 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004079 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004080 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004081 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004082 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004083 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004084 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004086 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004087 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004088 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004089 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004090 goto error;
4091 }
Radek Krejci73adb602015-07-02 18:07:40 +02004092
Michal Vasko345da0a2015-12-02 10:35:55 +01004093 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004094 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004096 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004097
4098error:
4099
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004100 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004101 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004102 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004105 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004106}
4107
Michal Vasko0d343d12015-08-24 14:57:36 +02004108/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004109static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004110read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4111 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004112{
Radek Krejcie0674f82015-06-15 13:58:51 +02004113 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004114 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004115 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004116 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004117 int r;
4118 int c_tpdf = 0;
4119
Radek Krejcie0674f82015-06-15 13:58:51 +02004120 /* init */
4121 memset(&root, 0, sizeof root);
4122
Michal Vasko38d01f72015-06-15 09:41:06 +02004123 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004124 if (!inout) {
4125 LOGMEM;
4126 return NULL;
4127 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004128 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004129
4130 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004131 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004132 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004133 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004134 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004135 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004136 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004137 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004138 }
4139
Radek Krejci76512572015-08-04 09:47:08 +02004140 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004141
Radek Krejci6a113852015-07-03 16:04:20 +02004142 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004143 goto error;
4144 }
4145
Radek Krejcia9544502015-08-14 08:24:29 +02004146 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4147
Michal Vasko38d01f72015-06-15 09:41:06 +02004148 /* data statements */
4149 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004150 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4151 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004152 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004153 continue;
4154 }
4155
Michal Vasko38d01f72015-06-15 09:41:06 +02004156 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 !strcmp(sub->name, "leaf-list") ||
4158 !strcmp(sub->name, "leaf") ||
4159 !strcmp(sub->name, "list") ||
4160 !strcmp(sub->name, "choice") ||
4161 !strcmp(sub->name, "uses") ||
4162 !strcmp(sub->name, "grouping") ||
4163 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004164 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004165 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004167 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004168 } else if (!strcmp(sub->name, "typedef")) {
4169 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004170
Michal Vasko38d01f72015-06-15 09:41:06 +02004171 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004172 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004174 }
4175 }
4176
4177 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4178 if (c_tpdf) {
4179 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004180 if (!inout->tpdf) {
4181 LOGMEM;
4182 goto error;
4183 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004184 }
4185
Radek Krejci73adb602015-07-02 18:07:40 +02004186 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004187 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4188 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004189 if (r) {
4190 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004191 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004192 }
4193
Michal Vasko6c629ac2016-02-15 14:08:23 +01004194 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004195 goto error;
4196 }
4197
Michal Vasko38d01f72015-06-15 09:41:06 +02004198 /* last part - process data nodes */
4199 LY_TREE_FOR_SAFE(root.child, next, sub) {
4200 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004201 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004202 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004203 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004204 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004205 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004206 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004207 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004208 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004209 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004210 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004211 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004212 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004213 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004214 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004215 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004216 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004217 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004218 goto error;
4219 }
Radek Krejci73adb602015-07-02 18:07:40 +02004220
Michal Vasko345da0a2015-12-02 10:35:55 +01004221 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004222 }
4223
Michal Vasko38d01f72015-06-15 09:41:06 +02004224 return retval;
4225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004226error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004227
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004228 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004229 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004230 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004231 }
4232
4233 return NULL;
4234}
4235
Michal Vasko0d343d12015-08-24 14:57:36 +02004236/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004237static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004238read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4239 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004240{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004241 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004242 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004243 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004244 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004245 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004246 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004247
Michal Vaskoc6551b32015-06-16 10:51:43 +02004248 memset(&root, 0, sizeof root);
4249
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004251 if (!notif) {
4252 LOGMEM;
4253 return NULL;
4254 }
Radek Krejci76512572015-08-04 09:47:08 +02004255 notif->nodetype = LYS_NOTIF;
4256 notif->prev = (struct lys_node *)notif;
4257 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004258
Radek Krejci6a113852015-07-03 16:04:20 +02004259 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004260 goto error;
4261 }
4262
Radek Krejcia9544502015-08-14 08:24:29 +02004263 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4264
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 /* process rpc's specific children */
4266 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004267 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4268 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004269 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004270 continue;
4271 }
4272
Michal Vasko0ea41032015-06-16 08:53:55 +02004273 /* data statements */
4274 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004275 !strcmp(sub->name, "leaf-list") ||
4276 !strcmp(sub->name, "leaf") ||
4277 !strcmp(sub->name, "list") ||
4278 !strcmp(sub->name, "choice") ||
4279 !strcmp(sub->name, "uses") ||
4280 !strcmp(sub->name, "grouping") ||
4281 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004282 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004283 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004286 } else if (!strcmp(sub->name, "typedef")) {
4287 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004288 } else if (!strcmp(sub->name, "if-feature")) {
4289 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004290 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004291 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004292 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004293 }
4294 }
4295
4296 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4297 if (c_tpdf) {
4298 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004299 if (!notif->tpdf) {
4300 LOGMEM;
4301 goto error;
4302 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004303 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004304 if (c_ftrs) {
4305 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004306 if (!notif->features) {
4307 LOGMEM;
4308 goto error;
4309 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004310 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004311
Radek Krejci73adb602015-07-02 18:07:40 +02004312 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004313 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004314 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4315 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004316 if (r) {
4317 goto error;
4318 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004319 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko217db072016-02-15 12:32:04 +01004320 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004321 notif->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01004322 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004323 goto error;
4324 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004325 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004326 }
4327
Michal Vasko6c629ac2016-02-15 14:08:23 +01004328 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004329 goto error;
4330 }
4331
Michal Vasko0ea41032015-06-16 08:53:55 +02004332 /* last part - process data nodes */
4333 LY_TREE_FOR_SAFE(root.child, next, sub) {
4334 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004335 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004336 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004337 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004338 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004339 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004340 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004341 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004342 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004343 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004344 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004345 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004346 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004347 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004348 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004349 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004350 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004351 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004352 goto error;
4353 }
Radek Krejci73adb602015-07-02 18:07:40 +02004354
Michal Vasko345da0a2015-12-02 10:35:55 +01004355 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004356 }
4357
Michal Vasko0ea41032015-06-16 08:53:55 +02004358 return retval;
4359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004361
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004362 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004363 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004364 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004365 }
4366
4367 return NULL;
4368}
4369
Michal Vasko0d343d12015-08-24 14:57:36 +02004370/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004371static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004372read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4373 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004374{
Radek Krejcie0674f82015-06-15 13:58:51 +02004375 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004376 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004377 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004378 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004379 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004380 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004381
Radek Krejcie0674f82015-06-15 13:58:51 +02004382 /* init */
4383 memset(&root, 0, sizeof root);
4384
Michal Vasko38d01f72015-06-15 09:41:06 +02004385 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004386 if (!rpc) {
4387 LOGMEM;
4388 return NULL;
4389 }
Radek Krejci76512572015-08-04 09:47:08 +02004390 rpc->nodetype = LYS_RPC;
4391 rpc->prev = (struct lys_node *)rpc;
4392 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004393
Radek Krejci6a113852015-07-03 16:04:20 +02004394 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004395 goto error;
4396 }
4397
Radek Krejcia9544502015-08-14 08:24:29 +02004398 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4399
Michal Vasko38d01f72015-06-15 09:41:06 +02004400 /* process rpc's specific children */
4401 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004402 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4403 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004404 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004405 continue;
4406 }
4407
Michal Vasko38d01f72015-06-15 09:41:06 +02004408 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004410 && (rpc->child->nodetype == LYS_INPUT
4411 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004412 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004413 goto error;
4414 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004415 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004416 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004417 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004419 && (rpc->child->nodetype == LYS_INPUT
4420 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004421 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004422 goto error;
4423 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004424 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004425 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004428 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004429 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004430 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004432 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004433 } else if (!strcmp(sub->name, "typedef")) {
4434 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004435 } else if (!strcmp(sub->name, "if-feature")) {
4436 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004437 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004438 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004439 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004440 }
4441 }
4442
4443 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4444 if (c_tpdf) {
4445 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004446 if (!rpc->tpdf) {
4447 LOGMEM;
4448 goto error;
4449 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004450 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004451 if (c_ftrs) {
4452 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004453 if (!rpc->features) {
4454 LOGMEM;
4455 goto error;
4456 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004457 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004458
Radek Krejci73adb602015-07-02 18:07:40 +02004459 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004460 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004461 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4462 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004463 if (r) {
4464 goto error;
4465 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004466 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01004467 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004468 rpc->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01004469 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004470 goto error;
4471 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004472 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004473 }
4474
Michal Vasko6c629ac2016-02-15 14:08:23 +01004475 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004476 goto error;
4477 }
4478
Michal Vasko38d01f72015-06-15 09:41:06 +02004479 /* last part - process data nodes */
4480 LY_TREE_FOR_SAFE(root.child, next, sub) {
4481 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004482 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004483 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004484 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004485 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004486 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004487 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004488 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004489 goto error;
4490 }
Radek Krejci73adb602015-07-02 18:07:40 +02004491
Michal Vasko345da0a2015-12-02 10:35:55 +01004492 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004493 }
4494
Michal Vasko38d01f72015-06-15 09:41:06 +02004495 return retval;
4496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004498
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004499 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004500 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004501 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004502 }
4503
4504 return NULL;
4505}
4506
Michal Vasko0d343d12015-08-24 14:57:36 +02004507/* logs directly
4508 *
Radek Krejci74705112015-06-05 10:25:44 +02004509 * resolve - referenced grouping should be bounded to the namespace (resolved)
4510 * only when uses does not appear in grouping. In a case of grouping's uses,
4511 * we just get information but we do not apply augment or refine to it.
4512 */
Radek Krejci76512572015-08-04 09:47:08 +02004513static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004514read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004515 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004516{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004518 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004519 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004521 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004525 if (!uses) {
4526 LOGMEM;
4527 return NULL;
4528 }
Radek Krejci76512572015-08-04 09:47:08 +02004529 uses->nodetype = LYS_USES;
4530 uses->prev = (struct lys_node *)uses;
4531 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004532
Radek Krejcia9544502015-08-14 08:24:29 +02004533 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004535
Michal Vaskoe0c59842015-09-24 13:52:20 +02004536 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4537 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 goto error;
4539 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004540
Radek Krejcia9544502015-08-14 08:24:29 +02004541 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004544 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004545 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4546 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004547 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004548 continue;
4549 }
4550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004551 if (!strcmp(sub->name, "refine")) {
4552 c_ref++;
4553 } else if (!strcmp(sub->name, "augment")) {
4554 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004555 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004556 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004557 } else if (!strcmp(sub->name, "when")) {
4558 if (uses->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01004559 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004560 goto error;
4561 }
4562
4563 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004564 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004565 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004566 goto error;
4567 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004568 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004570 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 }
4573 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004575 /* process properties with cardinality 0..n */
4576 if (c_ref) {
4577 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004578 if (!uses->refine) {
4579 LOGMEM;
4580 goto error;
4581 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 }
4583 if (c_aug) {
4584 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004585 if (!uses->augment) {
4586 LOGMEM;
4587 goto error;
4588 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004590 if (c_ftrs) {
4591 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004592 if (!uses->features) {
4593 LOGMEM;
4594 goto error;
4595 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004596 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004597
Michal Vasko6c629ac2016-02-15 14:08:23 +01004598 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004599 goto error;
4600 }
4601
Radek Krejcia9544502015-08-14 08:24:29 +02004602 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004603 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004604 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4605 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004606 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004607 goto error;
4608 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004609 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004610 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4611 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004612 if (r) {
4613 goto error;
4614 }
4615 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01004616 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004617 uses->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01004618 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004619 goto error;
4620 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 }
4622 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004623
Michal Vasko0bd29d12015-08-19 11:45:49 +02004624 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004625 goto error;
4626 }
Radek Krejci74705112015-06-05 10:25:44 +02004627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 if (resolve) {
4629 /* inherit config flag */
4630 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004631 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 } else {
4633 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004634 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 }
4636 }
Radek Krejcib388c152015-06-04 17:03:03 +02004637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004639
4640error:
4641
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004642 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004645}
4646
Michal Vasko0d343d12015-08-24 14:57:36 +02004647/* logs directly
4648 *
4649 * common code for yin_read_module() and yin_read_submodule()
4650 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651static int
Radek Krejcic071c542016-01-27 14:57:51 +01004652read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4653 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004654{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004656 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004657 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004658 struct lys_module *trg;
4659 struct lys_import *aux_imp;
4660 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004662 int i, j, r;
4663 int inc_size_aux = 0;
4664 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004665 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004666 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 +02004667
Radek Krejcic071c542016-01-27 14:57:51 +01004668 /* to simplify code, store the module/submodule being processed as trg */
4669 trg = submodule ? (struct lys_module*)submodule : module;
4670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 /* init */
4672 memset(&root, 0, sizeof root);
4673 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004674 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 /*
4677 * in the first run, we process elements with cardinality of 1 or 0..1 and
4678 * count elements with cardinality 0..n. Data elements (choices, containers,
4679 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4680 * need have all top-level and groupings already prepared at that time. In
4681 * the middle loop, we process other elements with carinality of 0..n since
4682 * we need to allocate arrays to store them.
4683 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004684 LY_TREE_FOR_SAFE(yin->child, next, child) {
4685 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004686 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004687 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 continue;
4689 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004690
Radek Krejcic071c542016-01-27 14:57:51 +01004691 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 if (module->ns) {
Radek Krejciadb57612016-02-16 13:34:34 +01004693 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 goto error;
4695 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004696 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004698 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004699 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 if (module->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004701 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 goto error;
4703 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004704 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004705 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004706 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 goto error;
4708 }
4709 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004710 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004711 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4712 if (submodule->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004713 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 goto error;
4715 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004716 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004717 if (value != submodule->belongsto->name) {
Radek Krejciadb57612016-02-16 13:34:34 +01004718 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 goto error;
4720 }
Radek Krejcif3886932015-06-04 17:36:06 +02004721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004723 if (!child->child) {
Radek Krejciadb57612016-02-16 13:34:34 +01004724 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), LY_VLOG_XML, child, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004725 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004726 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejciadb57612016-02-16 13:34:34 +01004727 LOGVAL(LYE_INSTMT, LOGLINE(child->child), LY_VLOG_XML, child->child, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004729 } else if (child->child->next) {
Radek Krejciadb57612016-02-16 13:34:34 +01004730 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), LY_VLOG_XML, child->child->next,
4731 child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 goto error;
4733 }
4734 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004735 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 /* check here differs from a generic prefix check, since this prefix
4737 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004738 */
Radek Krejcic6556022016-01-27 15:16:45 +01004739 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004740 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child->child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 goto error;
4742 }
Radek Krejcic071c542016-01-27 14:57:51 +01004743 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004746 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004747
4748 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004749 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004751 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004753 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004755 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004757 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004759 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004760 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004761 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004762 lyxml_unlink_elem(ctx, child, 2);
4763 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004764
Radek Krejci1d82ef62015-08-07 14:44:40 +02004765 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004766 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004767 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004768 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004771 } else if (!strcmp(child->name, "container") ||
4772 !strcmp(child->name, "leaf-list") ||
4773 !strcmp(child->name, "leaf") ||
4774 !strcmp(child->name, "list") ||
4775 !strcmp(child->name, "choice") ||
4776 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004777 !strcmp(child->name, "anyxml") ||
4778 !strcmp(child->name, "rpc") ||
4779 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004780 lyxml_unlink_elem(ctx, child, 2);
4781 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004782
Radek Krejci1d82ef62015-08-07 14:44:40 +02004783 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004784 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004785 lyxml_unlink_elem(ctx, child, 2);
4786 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004788 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004789 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004790 if (trg->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01004791 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004792 goto error;
4793 }
Radek Krejcic071c542016-01-27 14:57:51 +01004794 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004795 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004796 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 goto error;
4798 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004799 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004800 if (trg->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01004801 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 goto error;
4803 }
Radek Krejcic071c542016-01-27 14:57:51 +01004804 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004805 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004806 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004807 goto error;
4808 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004809 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004810 if (trg->org) {
Radek Krejciadb57612016-02-16 13:34:34 +01004811 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 goto error;
4813 }
Radek Krejcic071c542016-01-27 14:57:51 +01004814 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004815 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004816 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 goto error;
4818 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004819 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004820 if (trg->contact) {
Radek Krejciadb57612016-02-16 13:34:34 +01004821 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 goto error;
4823 }
Radek Krejcic071c542016-01-27 14:57:51 +01004824 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004825 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004826 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004827 goto error;
4828 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004829 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004831 if (version_flag) {
Radek Krejciadb57612016-02-16 13:34:34 +01004832 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 goto error;
4834 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004835 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 if (strcmp(value, "1")) {
Radek Krejciadb57612016-02-16 13:34:34 +01004837 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 goto error;
4839 }
Radek Krejcic071c542016-01-27 14:57:51 +01004840 version_flag = 1;
4841 if (!submodule) {
4842 module->version = 1;
4843 } /* 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 +01004844 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004845
Radek Krejci1d82ef62015-08-07 14:44:40 +02004846 } else if (!strcmp(child->name, "extension")) {
4847 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004848
Radek Krejci3d468122015-10-02 13:36:12 +02004849 /* we have the following supported (hardcoded) extensions: */
4850 /* ietf-netconf's get-filter-element-attributes */
4851 if (!strcmp(module->ns, LY_NSNC) &&
4852 !strcmp(value, "get-filter-element-attributes")) {
4853 LOGDBG("NETCONF filter extension found");
4854 /* NACM's default-deny-write and default-deny-all */
4855 } else if (!strcmp(module->ns, LY_NSNACM) &&
4856 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4857 LOGDBG("NACM extension found");
4858 /* other extensions are not supported, so inform about such an extension */
4859 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004860 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004861 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004862 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004864 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 }
4867 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004868
Radek Krejcic071c542016-01-27 14:57:51 +01004869 /* check for mandatory statements */
4870 if (submodule && !submodule->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004871 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004872 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004873 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 if (!module->ns) {
Radek Krejciadb57612016-02-16 13:34:34 +01004875 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 goto error;
4877 }
4878 if (!module->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004879 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004880 goto error;
4881 }
4882 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004884 /* allocate arrays for elements with cardinality of 0..n */
4885 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004886 trg->imp = calloc(c_imp, sizeof *trg->imp);
4887 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004888 LOGMEM;
4889 goto error;
4890 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 }
4892 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004893 trg->rev = calloc(c_rev, sizeof *trg->rev);
4894 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004895 LOGMEM;
4896 goto error;
4897 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 }
4899 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004900 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4901 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004902 LOGMEM;
4903 goto error;
4904 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 }
4906 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004907 trg->ident = calloc(c_ident, sizeof *trg->ident);
4908 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004909 LOGMEM;
4910 goto error;
4911 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 }
4913 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004914 trg->inc = calloc(c_inc, sizeof *trg->inc);
4915 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004916 LOGMEM;
4917 goto error;
4918 }
Radek Krejcic071c542016-01-27 14:57:51 +01004919 trg->inc_size = c_inc;
4920 /* trg->inc_size can be updated by the included submodules,
4921 * so we will use inc_size_aux here, trg->inc_size stores the
4922 * target size of the array
4923 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004925 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004926 trg->augment = calloc(c_aug, sizeof *trg->augment);
4927 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004928 LOGMEM;
4929 goto error;
4930 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004931 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004932 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004933 trg->features = calloc(c_ftrs, sizeof *trg->features);
4934 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004935 LOGMEM;
4936 goto error;
4937 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004938 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004939 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004940 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4941 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004942 LOGMEM;
4943 goto error;
4944 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004946
Michal Vasko2f7925f2015-10-21 15:06:56 +02004947 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4948 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004949 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004950 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4951 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 if (r) {
4953 goto error;
4954 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004957 for (i = 0; i < trg->imp_size - 1; i++) {
4958 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004959 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 +02004960 goto error;
4961 }
4962 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004963
Radek Krejci1d82ef62015-08-07 14:44:40 +02004964 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004965 memset(&inc, 0, sizeof inc);
4966 /* 1) pass module, not trg, since we want to pass the main module
4967 * 2) we cannot pass directly the structure in the array since
4968 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004969 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004970 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4971 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004972 if (r) {
4973 goto error;
4974 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004977 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004978 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 +01004979 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child, "Including submodule \"%s\" repeatedly.",
Michal Vasko27ab8222016-02-12 09:33:52 +01004980 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004981 goto error;
4982 }
4983 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004984
Radek Krejci1d82ef62015-08-07 14:44:40 +02004985 } else if (!strcmp(child->name, "revision")) {
4986 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004987 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004988 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004989 goto error;
4990 }
Radek Krejcic071c542016-01-27 14:57:51 +01004991 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004993 for (i = 0; i < trg->rev_size; i++) {
4994 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004995 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
4996 LOGVAL(LYE_SPEC, 0, 0, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 }
4998 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004999
Radek Krejci1d82ef62015-08-07 14:44:40 +02005000 LY_TREE_FOR(child->child, child2) {
5001 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005002 if (trg->rev[trg->rev_size].dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01005003 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 goto error;
5005 }
Radek Krejcic071c542016-01-27 14:57:51 +01005006 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5007 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 goto error;
5009 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005010 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005011 if (trg->rev[trg->rev_size].ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01005012 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 goto error;
5014 }
Radek Krejcic071c542016-01-27 14:57:51 +01005015 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5016 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 goto error;
5018 }
5019 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01005020 LOGVAL(LYE_INSTMT, LOGLINE(child2), LY_VLOG_XML, child2, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 goto error;
5022 }
5023 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005025 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005026 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005028 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005029 if (!value) {
5030 LOGMEM;
5031 goto error;
5032 }
Radek Krejcic071c542016-01-27 14:57:51 +01005033 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5034 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005036
Radek Krejcic071c542016-01-27 14:57:51 +01005037 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
5038 value = trg->rev[0].dsc;
5039 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5040 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005041 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005042
Radek Krejcic071c542016-01-27 14:57:51 +01005043 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
5044 value = trg->rev[0].ref;
5045 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5046 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 }
5048 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005049
Radek Krejcic071c542016-01-27 14:57:51 +01005050 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005051
Radek Krejci1d82ef62015-08-07 14:44:40 +02005052 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005053 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5054 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 if (r) {
5056 goto error;
5057 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005058
Radek Krejci1d82ef62015-08-07 14:44:40 +02005059 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005060 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5061 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005062 if (r) {
5063 goto error;
5064 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005065
Radek Krejci1d82ef62015-08-07 14:44:40 +02005066 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005067 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5068 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005069 if (r) {
5070 goto error;
5071 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005072
Radek Krejci1d82ef62015-08-07 14:44:40 +02005073 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005074 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5075 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005076 if (r) {
5077 goto error;
5078 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005079 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5080 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005082 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005083 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005084
Radek Krejcic071c542016-01-27 14:57:51 +01005085 if (submodule) {
5086 /* propagate imports into the main module */
5087 for (i = r = 0; i < submodule->imp_size; i++) {
5088 for (j = 0; j < module->imp_size; j++) {
5089 if (submodule->imp[i].module == module->imp[j].module &&
5090 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5091 /* check prefix match */
5092 if (submodule->imp[i].prefix != module->imp[j].prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01005093 LOGVAL(LYE_INID, LOGLINE(yin), LY_VLOG_XML, yin, submodule->imp[i].prefix,
Radek Krejcic071c542016-01-27 14:57:51 +01005094 "non-matching prefixes of imported module in main module and submodule");
5095 goto error;
5096 }
5097 break;
5098 }
5099 }
5100 if (j == module->imp_size) {
5101 /* new import */
5102 r++;
5103 }
5104 }
5105 if (r) {
5106 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5107 if (!aux_imp) {
5108 LOGMEM;
5109 goto error;
5110 }
5111 module->imp = aux_imp;
5112 for (i = r = 0; i < submodule->imp_size; i++) {
5113 for (j = 0; j < module->imp_size; j++) {
5114 if (submodule->imp[i].module == module->imp[j].module) {
5115 break;
5116 }
5117 }
5118 if (j == module->imp_size) {
5119 /* new import */
5120 /* check prefix uniqueness */
5121 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005122 LOGVAL(LYE_DUPID, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", submodule->imp[i].prefix);
Radek Krejcic071c542016-01-27 14:57:51 +01005123 goto error;
5124 }
5125 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5126 module->imp[module->imp_size + r].external = 1;
5127 r++;
5128 }
5129 }
5130 module->imp_size += r;
5131 }
5132
Michal Vaskoe2905632016-02-11 15:42:24 +01005133 /* propagate includes into the main module */
Radek Krejcic071c542016-01-27 14:57:51 +01005134 for (i = r = 0; i < submodule->inc_size; i++) {
5135 for (j = 0; j < module->inc_size; j++) {
5136 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5137 break;
5138 }
5139 }
5140 if (j == module->inc_size) {
5141 /* new include */
5142 r++;
5143 }
5144 }
5145
5146 if (r) {
5147 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5148 if (!aux_inc) {
5149 LOGMEM;
5150 goto error;
5151 }
5152 module->inc = aux_inc;
5153 for (i = r = 0; i < submodule->inc_size; i++) {
5154 for (j = 0; j < module->inc_size; j++) {
5155 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5156 break;
5157 }
5158 }
5159 if (j == module->inc_size) {
5160 /* new include */
5161 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5162 module->inc[module->inc_size + r].external = 1;
5163 r++;
5164 }
5165 }
5166 module->inc_size += r;
5167 }
5168 }
5169
Radek Krejcif5be10f2015-06-16 13:29:36 +02005170 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005171 * refer to them. Submodule's data nodes are stored in the
5172 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005174 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005175 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005176 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 goto error;
5178 }
Radek Krejci74705112015-06-05 10:25:44 +02005179
Michal Vasko345da0a2015-12-02 10:35:55 +01005180 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 }
Radek Krejci74705112015-06-05 10:25:44 +02005182
Radek Krejcif5be10f2015-06-16 13:29:36 +02005183 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005184 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005185
Radek Krejci1d82ef62015-08-07 14:44:40 +02005186 if (!strcmp(child->name, "container")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005187 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005188 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005189 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005190 } else if (!strcmp(child->name, "leaf")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005191 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005192 } else if (!strcmp(child->name, "list")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005193 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005194 } else if (!strcmp(child->name, "choice")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005195 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005196 } else if (!strcmp(child->name, "uses")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005197 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005198 } else if (!strcmp(child->name, "anyxml")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005199 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005200 } else if (!strcmp(child->name, "rpc")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005201 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005202 } else if (!strcmp(child->name, "notification")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005203 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005205 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005206 goto error;
5207 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005208
Michal Vasko345da0a2015-12-02 10:35:55 +01005209 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005210 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005211
Michal Vasko2f7925f2015-10-21 15:06:56 +02005212 /* ... and finally augments (last, so we can augment our data, for instance) */
5213 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005214 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5215 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005216
Michal Vasko2f7925f2015-10-21 15:06:56 +02005217 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005218 goto error;
5219 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005220 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005221 }
5222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005224
5225error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005226 /* cleanup */
5227 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005228 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005229 }
5230 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005231 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005232 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005233 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005234 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005235 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005237 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005238}
5239
Michal Vasko0d343d12015-08-24 14:57:36 +02005240/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005241struct lys_submodule *
5242yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005243{
Michal Vasko9f258e42016-02-11 11:36:27 +01005244 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005245 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005246 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005248 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005249
Michal Vasko5a721fd2016-02-16 12:16:48 +01005250 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005251
Radek Krejci722b0072016-02-01 17:09:45 +01005252 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005254 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005255 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 /* check root element */
5258 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejciadb57612016-02-16 13:34:34 +01005259 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005260 goto error;
5261 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005264 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005265 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005266 goto error;
5267 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005268
Michal Vasko5a721fd2016-02-16 12:16:48 +01005269 submodule = calloc(1, sizeof *submodule);
5270 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 LOGMEM;
5272 goto error;
5273 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005274
Michal Vasko5a721fd2016-02-16 12:16:48 +01005275 submodule->ctx = module->ctx;
5276 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5277 submodule->type = 1;
5278 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005279
Michal Vasko5a721fd2016-02-16 12:16:48 +01005280 LOGVRB("Reading submodule \"%s\".", submodule->name);
5281 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005282 goto error;
5283 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005286 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005287
Michal Vasko5a721fd2016-02-16 12:16:48 +01005288 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005289
Michal Vasko5a721fd2016-02-16 12:16:48 +01005290 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005291
5292error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005294 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005295 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005296
Michal Vasko5a721fd2016-02-16 12:16:48 +01005297 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005298 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005299 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005300 }
5301
Michal Vasko5a721fd2016-02-16 12:16:48 +01005302 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005303
Michal Vaskoff006c12016-02-17 11:15:19 +01005304 /* remove parsed data */
5305 LY_TREE_FOR_SAFE(module->data, next, elem) {
5306 if (elem->module == (struct lys_module *)submodule) {
5307 lys_node_free(elem, NULL, 0);
5308 }
5309 }
5310
5311 /* remove applied deviations */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005312 for (i = 0; i < submodule->deviation_size; ++i) {
Michal Vaskoff006c12016-02-17 11:15:19 +01005313 if (submodule->deviation[i].orig_node) {
5314 resolve_augment_schema_nodeid(submodule->deviation[i].target_name, NULL, module, (const struct lys_node **)&elem);
5315 lys_node_switch(elem, submodule->deviation[i].orig_node);
Michal Vasko9f258e42016-02-11 11:36:27 +01005316 }
5317 }
5318
5319 /* remove applied augments */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005320 for (i = 0; i < submodule->augment_size; ++i) {
5321 if (submodule->augment[i].target) {
5322 LY_TREE_FOR_SAFE(submodule->augment[i].target->child, next, elem) {
5323 if (elem->parent == (struct lys_node *)&submodule->augment[i]) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005324 lys_node_free(elem, NULL, 0);
Michal Vasko9f258e42016-02-11 11:36:27 +01005325 }
5326 }
5327 }
5328 }
5329
Michal Vasko5a721fd2016-02-16 12:16:48 +01005330 lys_submodule_free(submodule, NULL);
5331
5332 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005333}
5334
Michal Vasko0d343d12015-08-24 14:57:36 +02005335/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005336struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005337yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005338{
Michal Vasko9f258e42016-02-11 11:36:27 +01005339 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005341 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005342 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005343 const char *value;
5344 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005345
Radek Krejcic071c542016-01-27 14:57:51 +01005346 unres = calloc(1, sizeof *unres);
5347 if (!unres) {
5348 LOGMEM;
5349 return NULL;
5350 }
5351
Radek Krejci722b0072016-02-01 17:09:45 +01005352 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005353 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005354 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 /* check root element */
5358 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejciadb57612016-02-16 13:34:34 +01005359 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 goto error;
5361 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005363 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005364 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005365 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 goto error;
5367 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 module = calloc(1, sizeof *module);
5370 if (!module) {
5371 LOGMEM;
5372 goto error;
5373 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005375 module->ctx = ctx;
5376 module->name = lydict_insert(ctx, value, strlen(value));
5377 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005378 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005379
Michal Vasko9f258e42016-02-11 11:36:27 +01005380 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005381 if (read_sub_module(module, NULL, yin, unres)) {
5382 goto error;
5383 }
5384
5385 /* resolve rest of unres items */
5386 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005387 goto error;
5388 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005390 /* add to the context's list of modules */
5391 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005392 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005393 if (!newlist) {
5394 LOGMEM;
5395 goto error;
5396 }
5397 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5398 newlist[i] = NULL;
5399 }
5400 ctx->models.size *= 2;
5401 ctx->models.list = newlist;
5402 }
5403 for (i = 0; ctx->models.list[i]; i++) {
5404 /* check name (name/revision) and namespace uniqueness */
5405 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005406 if (ctx->models.list[i]->rev_size == module->rev_size) {
5407 /* both have the same number of revisions */
5408 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5409 /* both have the same revision -> we already have the same module */
5410 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005411 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005412
Michal Vasko9f258e42016-02-11 11:36:27 +01005413 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005414 module = ctx->models.list[i];
5415 if (implement && !module->implemented) {
5416 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005417 }
Radek Krejcic071c542016-01-27 14:57:51 +01005418
5419 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005420 }
5421 }
Radek Krejcif647e612015-07-30 11:36:07 +02005422 /* else (both elses) keep searching, for now the caller is just adding
5423 * another revision of an already present schema
5424 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005426 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 ctx->models.list[i]->name, module->name, module->ns);
5428 goto error;
5429 }
5430 }
5431 ctx->models.list[i] = module;
5432 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005433 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005434
Radek Krejcic071c542016-01-27 14:57:51 +01005435success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005437 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005438 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005439
Michal Vasko9f258e42016-02-11 11:36:27 +01005440 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005442 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005443
5444error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005445 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005446 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005447 unres_schema_free(module, &unres);
5448
5449 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005450 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005451 return NULL;
5452 }
5453
5454 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005455
Michal Vaskoff006c12016-02-17 11:15:19 +01005456 /* remove applied deviations */
Michal Vasko9f258e42016-02-11 11:36:27 +01005457 for (i = 0; i < module->deviation_size; ++i) {
Michal Vaskoff006c12016-02-17 11:15:19 +01005458 if (module->deviation[i].orig_node) {
5459 resolve_augment_schema_nodeid(module->deviation[i].target_name, NULL, module, (const struct lys_node **)&elem);
5460 lys_node_switch(elem, module->deviation[i].orig_node);
Michal Vasko9f258e42016-02-11 11:36:27 +01005461 }
5462 }
5463
5464 /* remove applied augments */
5465 for (i = 0; i < module->augment_size; ++i) {
5466 if (module->augment[i].target) {
5467 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5468 if (elem->parent == (struct lys_node *)&module->augment[i]) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005469 lys_node_free(elem, NULL, 0);
Michal Vasko9f258e42016-02-11 11:36:27 +01005470 }
5471 }
5472 }
5473 }
5474
5475 lys_free(module, NULL, 1);
5476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005477 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005478}