blob: d4227c27ca4229fceb2d8d0c4ec3e3d3660e6bc0 [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;
Radek Krejcieb00f512015-07-01 16:44:58 +02001250
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001251 ctx = module->ctx;
1252
Radek Krejcieb00f512015-07-01 16:44:58 +02001253 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001254 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001255 if (!dev->target_name) {
1256 goto error;
1257 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001258
1259 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001260 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1261 if (rc || !dev_target) {
Radek Krejciadb57612016-02-16 13:34:34 +01001262 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001263 goto error;
1264 }
Michal Vaskob7b068c2016-02-16 13:51:50 +01001265 if (dev_target->module == lys_module(module)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001266 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001267 goto error;
1268 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001269 dev->target_module = dev_target->module;
Radek Krejcieb00f512015-07-01 16:44:58 +02001270 /* mark the target module as deviated */
Michal Vasko60f4b452016-02-12 11:02:55 +01001271 dev->target_module->deviated = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001272
1273 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001274 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1275 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001276 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001277 continue;
1278 }
1279
Radek Krejcieb00f512015-07-01 16:44:58 +02001280 if (!strcmp(child->name, "description")) {
1281 if (dev->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01001282 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001283 goto error;
1284 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001285 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001286 if (!dev->dsc) {
1287 goto error;
1288 }
1289 } else if (!strcmp(child->name, "reference")) {
1290 if (dev->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01001291 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001292 goto error;
1293 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001294 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001295 if (!dev->ref) {
1296 goto error;
1297 }
1298 } else if (!strcmp(child->name, "deviate")) {
1299 c_dev++;
1300
Michal Vasko345da0a2015-12-02 10:35:55 +01001301 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001302 * further processed later
1303 */
1304 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001305
Radek Krejcieb00f512015-07-01 16:44:58 +02001306 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001307 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001308 goto error;
1309 }
1310
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001311 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001312 }
1313
1314 if (c_dev) {
1315 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001316 if (!dev->deviate) {
1317 LOGMEM;
1318 goto error;
1319 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001320 }
1321
1322 LY_TREE_FOR(yin->child, develem) {
1323 /* init */
1324 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001325 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001326 c_must = 0;
1327 c_uniq = 0;
1328
1329 /* get deviation type */
1330 GETVAL(value, develem, "value");
1331 if (!strcmp(value, "not-supported")) {
1332 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1333 /* no property expected in this case */
1334 if (develem->child) {
Radek Krejciadb57612016-02-16 13:34:34 +01001335 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), LY_VLOG_XML, develem->child, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001336 goto error;
1337 }
1338
Radek Krejci5b917642015-07-02 09:03:13 +02001339 /* and neither any other deviate statement is expected,
1340 * not-supported deviation must be the only deviation of the target
1341 */
1342 if (dev->deviate_size || develem->next) {
Radek Krejciadb57612016-02-16 13:34:34 +01001343 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
1344 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001345 goto error;
1346 }
1347
1348
Radek Krejcieb00f512015-07-01 16:44:58 +02001349 /* remove target node */
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001350 lys_node_free(dev_target, NULL, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001351
Radek Krejci5b917642015-07-02 09:03:13 +02001352 dev->deviate_size = 1;
1353 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001354 } else if (!strcmp(value, "add")) {
1355 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1356 } else if (!strcmp(value, "replace")) {
1357 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1358 } else if (!strcmp(value, "delete")) {
1359 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1360 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001361 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001362 goto error;
1363 }
1364 d = &dev->deviate[dev->deviate_size];
1365
1366 /* process deviation properties */
1367 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001368 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1369 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001370 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001371 continue;
1372 }
1373
Radek Krejcieb00f512015-07-01 16:44:58 +02001374 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001375 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001376 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001377 goto error;
1378 }
1379
1380 /* for we deviate from RFC 6020 and allow config property even it is/is not
1381 * specified in the target explicitly since config property inherits. So we expect
1382 * that config is specified in every node. But for delete, we check that the value
1383 * is the same as here in deviation
1384 */
1385 GETVAL(value, child, "value");
1386 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001387 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001388 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001389 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001390 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001391 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001392 goto error;
1393 }
1394
1395 if (d->mod == LY_DEVIATE_DEL) {
1396 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001397 if ((d->flags & LYS_CONFIG_MASK) != (dev_target->flags & LYS_CONFIG_MASK)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001398 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1399 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001400 goto error;
1401 }
1402 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001403 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001404
1405 /* ... and inherit config value from the target's parent */
Michal Vasko60f4b452016-02-12 11:02:55 +01001406 if (dev_target->parent) {
1407 dev_target->flags |= dev_target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001408 } else {
1409 /* default config is true */
Michal Vasko60f4b452016-02-12 11:02:55 +01001410 dev_target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001411 }
1412 } else { /* add and replace are the same in this case */
1413 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001414 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415
1416 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001417 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 }
1419 } else if (!strcmp(child->name, "default")) {
1420 if (d->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001421 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001422 goto error;
1423 }
1424 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001425 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001426
Michal Vasko60f4b452016-02-12 11:02:55 +01001427 if (dev_target->nodetype == LYS_CHOICE) {
1428 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001429
1430 if (d->mod == LY_DEVIATE_ADD) {
1431 /* check that there is no current value */
1432 if (choice->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001433 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1434 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 goto error;
1436 }
1437 }
1438
Michal Vasko3edeaf72016-02-11 13:17:43 +01001439 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001440 if (rc || !node) {
Radek Krejciadb57612016-02-16 13:34:34 +01001441 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001442 goto error;
1443 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001444 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001445 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001446 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1447 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001448 goto error;
1449 }
1450 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001451 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001452 if (!choice->dflt) {
1453 /* default branch not found */
Radek Krejciadb57612016-02-16 13:34:34 +01001454 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001455 goto error;
1456 }
1457 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001458 } else if (dev_target->nodetype == LYS_LEAF) {
1459 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001460
1461 if (d->mod == LY_DEVIATE_ADD) {
1462 /* check that there is no current value */
1463 if (leaf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01001464 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1465 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001466 goto error;
1467 }
1468 }
1469
1470 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001471 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001472 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1473 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001474 goto error;
1475 }
1476 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001477 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001478 leaf->dflt = NULL;
1479 } else { /* add (already checked) and replace */
1480 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001481 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001482
1483 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001484 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001485 }
1486 } else {
1487 /* invalid target for default value */
Radek Krejciadb57612016-02-16 13:34:34 +01001488 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1489 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001490 goto error;
1491 }
1492 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001493 if (d->flags & LYS_MAND_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001494 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001495 goto error;
1496 }
1497
1498 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001499 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejciadb57612016-02-16 13:34:34 +01001500 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1501 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
1504
1505 GETVAL(value, child, "value");
1506 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001507 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001508 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001509 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001510 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001511 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 goto error;
1513 }
1514
1515 if (d->mod == LY_DEVIATE_ADD) {
1516 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001517 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01001518 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1519 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001520 goto error;
1521 }
1522 }
1523
1524 if (d->mod == LY_DEVIATE_DEL) {
1525 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001526 if ((d->flags & LYS_MAND_MASK) != (dev_target->flags & LYS_MAND_MASK)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001527 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1528 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001529 goto error;
1530 }
1531 /* remove current mandatory value of the target */
Michal Vasko60f4b452016-02-12 11:02:55 +01001532 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001533 } else { /* add (already checked) and replace */
1534 /* remove current mandatory value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001535 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001536
1537 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001538 dev_target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001539 }
1540 } else if (!strcmp(child->name, "min-elements")) {
1541 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01001542 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 goto error;
1544 }
1545 f_min = 1;
1546
Michal Vasko60f4b452016-02-12 11:02:55 +01001547 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001548 goto error;
1549 }
1550 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001551 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01001552 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001553 goto error;
1554 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001555 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001556
Michal Vasko60f4b452016-02-12 11:02:55 +01001557 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001558 goto error;
1559 }
1560 } else if (!strcmp(child->name, "must")) {
1561 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001562 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 continue;
1564 } else if (!strcmp(child->name, "type")) {
1565 if (d->type) {
Radek Krejciadb57612016-02-16 13:34:34 +01001566 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001567 goto error;
1568 }
1569
1570 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001571 if (dev_target->nodetype == LYS_LEAF) {
1572 t = &((struct lys_node_leaf *)dev_target)->type;
1573 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1574 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001575 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001576 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1577 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001578 goto error;
1579 }
1580
1581 if (d->mod == LY_DEVIATE_ADD) {
1582 /* not allowed, type is always present at the target */
Radek Krejciadb57612016-02-16 13:34:34 +01001583 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1584 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001585 goto error;
1586 } else if (d->mod == LY_DEVIATE_DEL) {
1587 /* not allowed, type cannot be deleted from the target */
Radek Krejciadb57612016-02-16 13:34:34 +01001588 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1589 LOGVAL(LYE_SPEC, 0, 0, NULL, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001590 goto error;
1591 }
1592
1593 /* replace */
1594 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001595 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001596
1597 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001598 /* HACK for unres */
1599 t->der = (struct lys_tpdf *)child;
Michal Vasko60f4b452016-02-12 11:02:55 +01001600 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001601 goto error;
1602 }
1603 d->type = t;
1604 } else if (!strcmp(child->name, "unique")) {
1605 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001606 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001607 continue;
1608 } else if (!strcmp(child->name, "units")) {
1609 if (d->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01001610 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001611 goto error;
1612 }
1613
1614 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001615 if (dev_target->nodetype == LYS_LEAFLIST) {
1616 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1617 } else if (dev_target->nodetype == LYS_LEAF) {
1618 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001619 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001620 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1621 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 goto error;
1623 }
1624
1625 /* get units value */
1626 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001627 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001628
1629 /* apply to target */
1630 if (d->mod == LY_DEVIATE_ADD) {
1631 /* check that there is no current value */
1632 if (*stritem) {
Radek Krejciadb57612016-02-16 13:34:34 +01001633 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1634 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 goto error;
1636 }
1637 }
1638
1639 if (d->mod == LY_DEVIATE_DEL) {
1640 /* check values */
1641 if (*stritem != d->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01001642 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
1643 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 goto error;
1645 }
1646 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001647 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001648 } else { /* add (already checked) and replace */
1649 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001650 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001651
1652 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001653 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001654 }
1655 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001656 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001657 goto error;
1658 }
1659
Michal Vasko88c29542015-11-27 14:57:53 +01001660 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001661 }
1662
1663 if (c_must) {
1664 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001665 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001666 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001667 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1668 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001669 break;
Radek Krejci76512572015-08-04 09:47:08 +02001670 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001671 trg_must = &((struct lys_node_container *)dev_target)->must;
1672 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001673 break;
Radek Krejci76512572015-08-04 09:47:08 +02001674 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001675 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1676 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001677 break;
Radek Krejci76512572015-08-04 09:47:08 +02001678 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001679 trg_must = &((struct lys_node_list *)dev_target)->must;
1680 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001681 break;
Radek Krejci76512572015-08-04 09:47:08 +02001682 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001683 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1684 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001685 break;
1686 default:
Radek Krejciadb57612016-02-16 13:34:34 +01001687 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1688 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001689 goto error;
1690 }
1691
1692 if (d->mod == LY_DEVIATE_RPL) {
1693 /* remove target's musts and allocate new array for it */
1694 if (!*trg_must) {
Radek Krejciadb57612016-02-16 13:34:34 +01001695 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, "replace", "deviate");
1696 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 goto error;
1698 }
1699
1700 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001701 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001702 }
1703 free(*trg_must);
1704 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1705 d->must_size = c_must;
1706 *trg_must_size = 0;
1707 } else if (d->mod == LY_DEVIATE_ADD) {
1708 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001709 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001710 if (!d->must) {
1711 LOGMEM;
1712 goto error;
1713 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001714 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001715 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 d->must_size = c_must;
1717 } else { /* LY_DEVIATE_DEL */
1718 d->must = calloc(c_must, sizeof *d->must);
1719 }
Michal Vasko253035f2015-12-17 16:58:13 +01001720 if (!d->must) {
1721 LOGMEM;
1722 goto error;
1723 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001724 }
1725 if (c_uniq) {
1726 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001727 if (dev_target->nodetype != LYS_LIST) {
Radek Krejciadb57612016-02-16 13:34:34 +01001728 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
1729 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001730 goto error;
1731 }
1732
Michal Vasko60f4b452016-02-12 11:02:55 +01001733 list = (struct lys_node_list *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001734 if (d->mod == LY_DEVIATE_RPL) {
1735 /* remove target's unique and allocate new array for it */
1736 if (!list->unique) {
Radek Krejciadb57612016-02-16 13:34:34 +01001737 LOGVAL(LYE_INARG, LOGLINE(develem), LY_VLOG_XML, develem, "replace", "deviate");
1738 LOGVAL(LYE_SPEC, 0, 0, NULL, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001739 goto error;
1740 }
1741
1742 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001743 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001744 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001745 }
1746 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 }
1748 free(list->unique);
1749 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1750 d->unique_size = c_uniq;
1751 list->unique_size = 0;
1752 } else if (d->mod == LY_DEVIATE_ADD) {
1753 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001754 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001755 list->unique = d->unique;
1756 d->unique = &list->unique[list->unique_size];
1757 d->unique_size = c_uniq;
1758 } else { /* LY_DEVIATE_DEL */
1759 d->unique = calloc(c_uniq, sizeof *d->unique);
1760 }
Michal Vasko253035f2015-12-17 16:58:13 +01001761 if (!d->unique) {
1762 LOGMEM;
1763 goto error;
1764 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001765 }
1766
1767 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001768 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001769 if (!strcmp(child->name, "must")) {
1770 if (d->mod == LY_DEVIATE_DEL) {
1771 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1772 goto error;
1773 }
1774
1775 /* find must to delete, we are ok with just matching conditions */
1776 for (i = 0; i < *trg_must_size; i++) {
1777 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1778 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001779 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001780 /* ... and maintain the array */
1781 (*trg_must_size)--;
1782 if (i != *trg_must_size) {
1783 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1784 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1785 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1786 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1787 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1788 }
1789 if (!(*trg_must_size)) {
1790 free(*trg_must);
1791 *trg_must = NULL;
1792 } else {
1793 (*trg_must)[*trg_must_size].expr = NULL;
1794 (*trg_must)[*trg_must_size].dsc = NULL;
1795 (*trg_must)[*trg_must_size].ref = NULL;
1796 (*trg_must)[*trg_must_size].eapptag = NULL;
1797 (*trg_must)[*trg_must_size].emsg = NULL;
1798 }
1799
1800 i = -1; /* set match flag */
1801 break;
1802 }
1803 }
1804 d->must_size++;
1805 if (i != -1) {
1806 /* no match found */
Radek Krejciadb57612016-02-16 13:34:34 +01001807 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child,
1808 d->must[d->must_size - 1].expr, child->name);
1809 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001810 goto error;
1811 }
1812 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001813 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1814 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001815 goto error;
1816 }
1817 (*trg_must_size)++;
1818 }
1819 } else if (!strcmp(child->name, "unique")) {
1820 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001821 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001822 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 goto error;
1824 }
1825
1826 /* find unique structures to delete */
1827 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001828 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001829 continue;
1830 }
1831
Radek Krejci581ce772015-11-10 17:22:40 +01001832 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1833 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001834 break;
1835 }
1836 }
1837
Radek Krejci581ce772015-11-10 17:22:40 +01001838 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001839 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001840 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001841 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001842 }
1843 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 /* ... and maintain the array */
1845 list->unique_size--;
1846 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001847 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1848 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001849 }
1850
1851 if (!list->unique_size) {
1852 free(list->unique);
1853 list->unique = NULL;
1854 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001855 list->unique[list->unique_size].expr_size = 0;
1856 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 }
1858
1859 i = -1; /* set match flag */
1860 break;
1861 }
1862 }
1863
1864 d->unique_size++;
1865 if (i != -1) {
1866 /* no match found */
Radek Krejciadb57612016-02-16 13:34:34 +01001867 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, lyxml_get_attr(child, "tag", NULL), child->name);
1868 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001869 goto error;
1870 }
1871 } else { /* replace or add */
Michal Vasko60f4b452016-02-12 11:02:55 +01001872 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001873 list->unique_size++;
1874 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001875 goto error;
1876 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001877 }
1878 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001879 }
Radek Krejci5b917642015-07-02 09:03:13 +02001880
1881 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001882 }
1883
Radek Krejcieb00f512015-07-01 16:44:58 +02001884 return EXIT_SUCCESS;
1885
1886error:
1887
Radek Krejcieb00f512015-07-01 16:44:58 +02001888 return EXIT_FAILURE;
1889}
1890
Michal Vasko0d343d12015-08-24 14:57:36 +02001891/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001892static int
Radek Krejcib8048692015-08-05 13:36:34 +02001893fill_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 +02001894 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001895{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001897 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001899 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001900
Michal Vasko591e0b22015-08-13 13:53:43 +02001901 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001903 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001904 if (!aug->target_name) {
1905 goto error;
1906 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001908
Michal Vasko1d87a922015-08-21 12:57:16 +02001909 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001910 goto error;
1911 }
1912
1913 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001914 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1915 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001916 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001917 continue;
1918 }
1919
Radek Krejci3cf9e222015-06-18 11:37:50 +02001920 if (!strcmp(child->name, "if-feature")) {
1921 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001923 } else if (!strcmp(child->name, "when")) {
1924 if (aug->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01001925 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001926 goto error;
1927 }
1928
1929 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001930 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001931 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001932 goto error;
1933 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001934 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001935 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001936
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001937 /* check allowed data sub-statements */
1938 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001939 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001940 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001941 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001942 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001943 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001944 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001946 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001947 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001948 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001950 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001951 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001952 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001953 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001954 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01001955 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001956 goto error;
1957 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958
Radek Krejci1d82ef62015-08-07 14:44:40 +02001959 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001960 goto error;
1961 }
1962
1963 /* check for mandatory nodes - if the target node is in another module
1964 * the added nodes cannot be mandatory
1965 */
Radek Krejcic6556022016-01-27 15:16:45 +01001966 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Radek Krejciadb57612016-02-16 13:34:34 +01001967 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child,
1968 "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001969 goto error;
1970 }
1971
Radek Krejci1d82ef62015-08-07 14:44:40 +02001972 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001973 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001974 }
1975
1976 if (c) {
1977 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001978 if (!aug->features) {
1979 LOGMEM;
1980 goto error;
1981 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001982 }
1983
1984 LY_TREE_FOR_SAFE(yin->child, next, child) {
1985 if (!strcmp(child->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01001986 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001987 aug->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01001988 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001989 goto error;
1990 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001991 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001992 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001993 }
1994
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02001996 * connected to the tree and adjusted (if possible right now).
1997 * However, if this is augment in a uses, it gets resolved
1998 * when the uses does and cannot be resolved now for sure
1999 * (the grouping was not yet copied into uses).
2000 */
2001 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko7178e692016-02-12 15:58:05 +01002002 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin)) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002003 goto error;
2004 }
Michal Vasko49291b32015-08-06 09:49:41 +02002005 }
Radek Krejci106efc02015-06-10 14:36:27 +02002006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002007 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002008
2009error:
2010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002011 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002012}
2013
Michal Vasko0d343d12015-08-24 14:57:36 +02002014/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002015static int
Michal Vasko0d204592015-10-07 09:50:04 +02002016fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002017{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 struct lyxml_elem *sub, *next;
2019 const char *value;
2020 char *endptr;
2021 int f_mand = 0, f_min = 0, f_max = 0;
2022 int c_must = 0;
2023 int r;
2024 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002025
Radek Krejci76512572015-08-04 09:47:08 +02002026 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 goto error;
2028 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002029
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002030 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002031 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002032 if (!rfn->target_name) {
2033 goto error;
2034 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002037 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2038 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002039 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002040 continue;
2041 }
2042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002043 /* limited applicability */
2044 if (!strcmp(sub->name, "default")) {
2045 /* leaf or choice */
2046 if (rfn->mod.dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01002047 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 goto error;
2049 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002051 /* check possibility of statements combination */
2052 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002053 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002055 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 goto error;
2057 }
2058 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002059 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 GETVAL(value, sub, "value");
2063 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2064 } else if (!strcmp(sub->name, "mandatory")) {
2065 /* leaf, choice or anyxml */
2066 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002067 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 goto error;
2069 }
2070 /* just checking the flags in leaf is not sufficient, we would allow
2071 * multiple mandatory statements with the "false" value
2072 */
2073 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 /* check possibility of statements combination */
2076 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002077 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002079 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002080 goto error;
2081 }
2082 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002083 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 GETVAL(value, sub, "value");
2087 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002088 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002090 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002092 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 goto error;
2094 }
2095 } else if (!strcmp(sub->name, "min-elements")) {
2096 /* list or leaf-list */
2097 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01002098 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 goto error;
2100 }
2101 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 /* check possibility of statements combination */
2104 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002105 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002107 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 goto error;
2109 }
2110 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002111 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 GETVAL(value, sub, "value");
2115 while (isspace(value[0])) {
2116 value++;
2117 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 /* convert it to uint32_t */
2120 errno = 0;
2121 endptr = NULL;
2122 val = strtoul(value, &endptr, 10);
2123 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01002124 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 goto error;
2126 }
2127 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 /* magic - bit 3 in flags means min set */
2130 rfn->flags |= 0x04;
2131 } else if (!strcmp(sub->name, "max-elements")) {
2132 /* list or leaf-list */
2133 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01002134 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 goto error;
2136 }
2137 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 /* check possibility of statements combination */
2140 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002141 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002143 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 goto error;
2145 }
2146 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002147 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 GETVAL(value, sub, "value");
2151 while (isspace(value[0])) {
2152 value++;
2153 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002154
Radek Krejci0d7b2472016-02-12 11:11:03 +01002155 if (!strcmp(value, "unbounded")) {
2156 rfn->mod.list.max = 0;
2157 } else {
2158 /* convert it to uint32_t */
2159 errno = 0;
2160 endptr = NULL;
2161 val = strtoul(value, &endptr, 10);
2162 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01002163 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002164 goto error;
2165 }
2166 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 /* magic - bit 4 in flags means min set */
2170 rfn->flags |= 0x08;
2171 } else if (!strcmp(sub->name, "presence")) {
2172 /* container */
2173 if (rfn->mod.presence) {
Radek Krejciadb57612016-02-16 13:34:34 +01002174 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 goto error;
2176 }
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_CONTAINER;
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_CONTAINER;
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 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2191 } else if (!strcmp(sub->name, "must")) {
2192 /* leaf-list, list, container or anyxml */
2193 /* check possibility of statements combination */
2194 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002195 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 if (!rfn->target_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01002197 LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_XML, sub, "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 goto error;
2199 }
2200 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002201 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002205 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002208 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 goto error;
2210 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002211
Michal Vasko345da0a2015-12-02 10:35:55 +01002212 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 /* process nodes with cardinality of 0..n */
2216 if (c_must) {
2217 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002218 if (!rfn->must) {
2219 LOGMEM;
2220 goto error;
2221 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 }
Radek Krejci73adb602015-07-02 18:07:40 +02002223 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002224 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2225 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002226 if (r) {
2227 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002232
2233error:
2234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002236}
2237
Michal Vasko0d343d12015-08-24 14:57:36 +02002238/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239static int
Radek Krejcib8048692015-08-05 13:36:34 +02002240fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002241{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 struct lyxml_elem *child;
2243 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002244 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002247 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2248 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002249 continue;
2250 }
2251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 if (!strcmp(child->name, "prefix")) {
2253 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002254 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002255 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 goto error;
2257 }
2258 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2259 } else if (!strcmp(child->name, "revision-date")) {
2260 if (imp->rev[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +01002261 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 goto error;
2263 }
2264 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002265 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01002266 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002267 goto error;
2268 }
2269 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2270 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002271 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 goto error;
2273 }
2274 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 /* check mandatory information */
2277 if (!imp->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01002278 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 goto error;
2280 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002283
2284 /* check for circular import, store it if passed */
2285 if (!module->ctx->models.parsing) {
2286 count = 0;
2287 } else {
2288 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2289 if (value == module->ctx->models.parsing[count]) {
2290 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2291 goto error;
2292 }
2293 }
2294 }
2295 ++count;
2296 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002297 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2298 if (!module->ctx->models.parsing) {
2299 LOGMEM;
2300 goto error;
2301 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002302 module->ctx->models.parsing[count - 1] = value;
2303 module->ctx->models.parsing[count] = NULL;
2304
2305 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002306 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 +02002307 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002308 /* whether to use a user callback is decided in the function */
2309 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 +02002310 }
2311
2312 /* remove the new module name now that its parsing is finished (even if failed) */
2313 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2314 LOGINT;
2315 }
2316 --count;
2317 if (count) {
2318 module->ctx->models.parsing[count] = NULL;
2319 } else {
2320 free(module->ctx->models.parsing);
2321 module->ctx->models.parsing = NULL;
2322 }
2323
2324 /* check the result */
2325 if (!imp->module) {
Radek Krejciadb57612016-02-16 13:34:34 +01002326 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002327 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2328 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002332
2333error:
2334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002336}
2337
Michal Vasko0d343d12015-08-24 14:57:36 +02002338/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002339static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002340fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2341 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002342{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 struct lyxml_elem *child;
2344 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002345 char *module_data;
2346 void (*module_data_free)(char *module_data) = NULL;
2347 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko5a721fd2016-02-16 12:16:48 +01002348 int count, i;
Radek Krejciefaeba32015-05-27 14:30:57 +02002349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002351 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2352 /* garbage */
2353 continue;
2354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 if (!strcmp(child->name, "revision-date")) {
2356 if (inc->rev[0]) {
Radek Krejciadb57612016-02-16 13:34:34 +01002357 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 goto error;
2359 }
2360 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002361 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01002362 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363 goto error;
2364 }
2365 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2366 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002367 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368 goto error;
2369 }
2370 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002373
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002374 /* check that the submodule was not included yet (previous submodule could have included it) */
2375 for (i = 0; i < module->inc_size; ++i) {
2376 if (module->inc[i].submodule && (module->inc[i].submodule->name == value)) {
Michal Vasko5ff78822016-02-12 09:33:31 +01002377 /* copy the duplicate into the result */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002378 memcpy(inc, &module->inc[i], sizeof *inc);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002379
Michal Vasko5ff78822016-02-12 09:33:31 +01002380 if (submodule) {
2381 /* we don't care if it was external or not */
2382 inc->external = 0;
2383 } else if (inc->external) {
2384 /* remove the duplicate */
2385 --module->inc_size;
2386 memmove(&module->inc[i], &module->inc[i + 1], (module->inc_size - i) * sizeof *inc);
2387 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
2388
2389 /* it is no longer external */
2390 inc->external = 0;
2391 }
2392 /* if !submodule && !inc->external, we just create a duplicate so it is detected and ended with error */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002393
2394 return EXIT_SUCCESS;
2395 }
2396 }
2397
Michal Vasko1b882eb2015-10-22 11:43:14 +02002398 /* check for circular include, store it if passed */
2399 if (!module->ctx->models.parsing) {
2400 count = 0;
2401 } else {
2402 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2403 if (value == module->ctx->models.parsing[count]) {
2404 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2405 goto error;
2406 }
2407 }
2408 }
2409 ++count;
2410 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002411 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2412 if (!module->ctx->models.parsing) {
2413 LOGMEM;
2414 goto error;
2415 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002416 module->ctx->models.parsing[count - 1] = value;
2417 module->ctx->models.parsing[count] = NULL;
2418
2419 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002420 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002422 if (module->ctx->module_clb) {
2423 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2424 &format, &module_data_free);
2425 if (module_data) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01002426 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002427 if (module_data_free) {
2428 module_data_free(module_data);
2429 } else {
2430 free(module_data);
2431 }
2432 } else {
2433 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2434 }
2435 } else {
Michal Vasko5a721fd2016-02-16 12:16:48 +01002436 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
2437 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002438 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002439 }
2440
2441 /* remove the new submodule name now that its parsing is finished (even if failed) */
2442 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2443 LOGINT;
2444 }
2445 --count;
2446 if (count) {
2447 module->ctx->models.parsing[count] = NULL;
2448 } else {
2449 free(module->ctx->models.parsing);
2450 module->ctx->models.parsing = NULL;
2451 }
2452
2453 /* check the result */
Michal Vasko5a721fd2016-02-16 12:16:48 +01002454 if (!inc->submodule) {
Radek Krejciadb57612016-02-16 13:34:34 +01002455 LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_XML, yin, value, yin->name);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002456 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2457 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002461
2462error:
2463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002464 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002465}
2466
Michal Vasko0d343d12015-08-24 14:57:36 +02002467/* logs directly
2468 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002469 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002470 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002471 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002472 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473static int
Radek Krejcib8048692015-08-05 13:36:34 +02002474read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002475 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002476{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 const char *value;
2478 struct lyxml_elem *sub, *next;
2479 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002482 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 if (opt & OPT_IDENT) {
2486 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002487 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002488 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, xmlnode);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 goto error;
2490 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002491 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002493
Radek Krejci6764bb32015-07-03 15:16:04 +02002494 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002495 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002496 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002497 }
2498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 /* process local parameters */
2500 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002501 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002502 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002503 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002504 continue;
2505 }
2506 if (strcmp(sub->ns->value, LY_NSYIN)) {
2507 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002508 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002509 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002510 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002511 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002512 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002513 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002514 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002515 goto error;
2516 }
2517 }
2518
2519 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002520 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002521 continue;
2522 }
2523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002525 if (node->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01002526 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 goto error;
2528 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002529 node->dsc = read_yin_subnode(ctx, sub, "text");
2530 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002531 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002532 }
2533 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002534 if (node->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01002535 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002536 goto error;
2537 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002538 node->ref = read_yin_subnode(ctx, sub, "text");
2539 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002540 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 }
2542 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002543 if (node->flags & LYS_STATUS_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01002544 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 goto error;
2546 }
2547 GETVAL(value, sub, "value");
2548 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002549 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002551 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002553 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002554 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002555 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002556 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002557 }
2558 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002559 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejciadb57612016-02-16 13:34:34 +01002560 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002561 goto error;
2562 }
2563 GETVAL(value, sub, "value");
2564 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002565 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002566 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002567 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002568 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002569 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002570 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 }
2572 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002573 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002574 continue;
2575 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002576 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002578
Radek Krejci1d82ef62015-08-07 14:44:40 +02002579 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 /* get config flag from parent */
2581 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002582 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002583 } else {
2584 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002585 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002586 }
2587 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002589 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002590
2591error:
2592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002593 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002594}
2595
Michal Vasko0d343d12015-08-24 14:57:36 +02002596/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002597static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002598read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002599{
Radek Krejci76512572015-08-04 09:47:08 +02002600 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002601 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002602 const char *value;
2603
2604 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002605 if (!retval) {
2606 LOGMEM;
2607 return NULL;
2608 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002609
2610 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002611 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002612 if (!retval->cond) {
2613 goto error;
2614 }
Michal Vasko27f2da82016-02-15 12:32:42 +01002615 if (lyxp_syntax_check(retval->cond, LOGLINE(yin))) {
2616 goto error;
2617 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002618
Radek Krejci73adb602015-07-02 18:07:40 +02002619 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002620 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2621 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002622 continue;
2623 }
2624
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002625 if (!strcmp(child->name, "description")) {
2626 if (retval->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01002627 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002628 goto error;
2629 }
2630 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2631 if (!retval->dsc) {
2632 goto error;
2633 }
2634 } else if (!strcmp(child->name, "reference")) {
2635 if (retval->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01002636 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002637 goto error;
2638 }
2639 retval->ref = read_yin_subnode(module->ctx, child, "text");
2640 if (!retval->ref) {
2641 goto error;
2642 }
2643 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002644 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002645 goto error;
2646 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002647 }
2648
2649 return retval;
2650
2651error:
2652
Michal Vasko0308dd62015-10-07 09:14:40 +02002653 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002654 return NULL;
2655}
2656
Michal Vasko0d343d12015-08-24 14:57:36 +02002657/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002658static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002659read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2660 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002661{
Michal Vasko29fc0182015-08-24 15:02:39 +02002662 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002663 struct lys_node_case *cs;
2664 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002665 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002666
Radek Krejcie867c852015-08-27 09:52:34 +02002667 /* init */
2668 memset(&root, 0, sizeof root);
2669
Radek Krejci1d82ef62015-08-07 14:44:40 +02002670 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002671 if (!cs) {
2672 LOGMEM;
2673 return NULL;
2674 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002675 cs->nodetype = LYS_CASE;
2676 cs->prev = (struct lys_node *)cs;
2677 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002678
Radek Krejci6a113852015-07-03 16:04:20 +02002679 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 goto error;
2681 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002682
Radek Krejcia9544502015-08-14 08:24:29 +02002683 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2684
Michal Vasko3a0043f2015-08-12 12:11:30 +02002685 /* insert the node into the schema tree */
Michal Vasko6c629ac2016-02-15 14:08:23 +01002686 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002687 goto error;
2688 }
2689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 /* process choice's specific children */
2691 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002692 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2693 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002694 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002695 continue;
2696 }
2697
Michal Vasko29fc0182015-08-24 15:02:39 +02002698 if (!strcmp(sub->name, "container") ||
2699 !strcmp(sub->name, "leaf-list") ||
2700 !strcmp(sub->name, "leaf") ||
2701 !strcmp(sub->name, "list") ||
2702 !strcmp(sub->name, "uses") ||
2703 !strcmp(sub->name, "choice") ||
2704 !strcmp(sub->name, "anyxml")) {
2705
Michal Vaskof3930de2015-10-22 12:03:59 +02002706 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002707 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002708 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002709 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002710 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002711 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002712 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002713 if (cs->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002714 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002715 goto error;
2716 }
2717
Radek Krejci1d82ef62015-08-07 14:44:40 +02002718 cs->when = read_yin_when(module, sub);
2719 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002720 goto error;
2721 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002722
Michal Vasko345da0a2015-12-02 10:35:55 +01002723 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002725 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002726 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002729
Radek Krejci3cf9e222015-06-18 11:37:50 +02002730 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002731 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002732 if (!cs->features) {
2733 LOGMEM;
2734 goto error;
2735 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002736 }
Radek Krejci73adb602015-07-02 18:07:40 +02002737 LY_TREE_FOR(yin->child, sub) {
Michal Vasko217db072016-02-15 12:32:04 +01002738 ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002739 cs->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01002740 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002741 goto error;
2742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 }
Radek Krejcib388c152015-06-04 17:03:03 +02002744
Michal Vasko29fc0182015-08-24 15:02:39 +02002745 /* last part - process data nodes */
2746 LY_TREE_FOR_SAFE(root.child, next, sub) {
2747 if (!strcmp(sub->name, "container")) {
2748 node = read_yin_container(module, retval, sub, resolve, unres);
2749 } else if (!strcmp(sub->name, "leaf-list")) {
2750 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2751 } else if (!strcmp(sub->name, "leaf")) {
2752 node = read_yin_leaf(module, retval, sub, resolve, unres);
2753 } else if (!strcmp(sub->name, "list")) {
2754 node = read_yin_list(module, retval, sub, resolve, unres);
2755 } else if (!strcmp(sub->name, "choice")) {
2756 node = read_yin_choice(module, retval, sub, resolve, unres);
2757 } else if (!strcmp(sub->name, "uses")) {
2758 node = read_yin_uses(module, retval, sub, resolve, unres);
2759 } else if (!strcmp(sub->name, "anyxml")) {
2760 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2761 }
2762 if (!node) {
2763 goto error;
2764 }
2765
Michal Vasko345da0a2015-12-02 10:35:55 +01002766 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002767 }
2768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002770
2771error:
2772
Michal Vasko29fc0182015-08-24 15:02:39 +02002773 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002774 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002775 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002776 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002778 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002779}
2780
Michal Vasko0d343d12015-08-24 14:57:36 +02002781/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002782static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002783read_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 +02002784{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 struct lyxml_elem *sub, *next;
2786 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002787 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002788 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002789 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002790 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002793 if (!choice) {
2794 LOGMEM;
2795 return NULL;
2796 }
Radek Krejci76512572015-08-04 09:47:08 +02002797 choice->nodetype = LYS_CHOICE;
2798 choice->prev = (struct lys_node *)choice;
2799 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002800
Michal Vaskoe0c59842015-09-24 13:52:20 +02002801 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2802 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 goto error;
2804 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002805
Radek Krejcia9544502015-08-14 08:24:29 +02002806 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2807
Michal Vasko3a0043f2015-08-12 12:11:30 +02002808 /* insert the node into the schema tree */
Michal Vasko6c629ac2016-02-15 14:08:23 +01002809 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002810 goto error;
2811 }
2812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002813 /* process choice's specific children */
2814 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002815 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2816 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002817 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002818 continue;
2819 }
2820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002822 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 goto error;
2824 }
2825 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002826 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002827 goto error;
2828 }
2829 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002830 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 goto error;
2832 }
2833 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002834 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002835 goto error;
2836 }
2837 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002838 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 goto error;
2840 }
2841 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002842 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002843 goto error;
2844 }
2845 } else if (!strcmp(sub->name, "default")) {
2846 if (dflt_str) {
Radek Krejciadb57612016-02-16 13:34:34 +01002847 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 goto error;
2849 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002850 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002851 } else if (!strcmp(sub->name, "mandatory")) {
2852 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002853 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002854 goto error;
2855 }
2856 /* just checking the flags in leaf is not sufficient, we would allow
2857 * multiple mandatory statements with the "false" value
2858 */
2859 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 GETVAL(value, sub, "value");
2862 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002863 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002864 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002865 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002866 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002867 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002868 goto error;
2869 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002870 } else if (!strcmp(sub->name, "when")) {
2871 if (choice->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002872 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002873 goto error;
2874 }
2875
2876 choice->when = read_yin_when(module, sub);
2877 if (!choice->when) {
2878 goto error;
2879 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002880 } else if (!strcmp(sub->name, "if-feature")) {
2881 c_ftrs++;
2882
Michal Vasko345da0a2015-12-02 10:35:55 +01002883 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002884 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002886 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002887 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002889
Radek Krejci1d82ef62015-08-07 14:44:40 +02002890 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002891 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002893
Radek Krejci3cf9e222015-06-18 11:37:50 +02002894 if (c_ftrs) {
2895 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002896 if (!choice->features) {
2897 LOGMEM;
2898 goto error;
2899 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002900 }
2901
Radek Krejci73adb602015-07-02 18:07:40 +02002902 LY_TREE_FOR(yin->child, sub) {
Michal Vasko217db072016-02-15 12:32:04 +01002903 ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002904 choice->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01002905 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002906 goto error;
2907 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002908 }
2909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002911 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejciadb57612016-02-16 13:34:34 +01002912 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2914 goto error;
2915 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 /* link default with the case */
2918 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002919 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002920 goto error;
2921 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002925
2926error:
2927
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002928 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002930 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002931}
2932
Michal Vasko0d343d12015-08-24 14:57:36 +02002933/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002934static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002935read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002936 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002937{
Radek Krejci76512572015-08-04 09:47:08 +02002938 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002939 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002940 struct lyxml_elem *sub, *next;
2941 const char *value;
2942 int r;
2943 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002944 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002947 if (!anyxml) {
2948 LOGMEM;
2949 return NULL;
2950 }
Radek Krejci76512572015-08-04 09:47:08 +02002951 anyxml->nodetype = LYS_ANYXML;
2952 anyxml->prev = (struct lys_node *)anyxml;
2953 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002954
Michal Vaskoe0c59842015-09-24 13:52:20 +02002955 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2956 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 goto error;
2958 }
Radek Krejci863c2852015-06-03 15:47:11 +02002959
Radek Krejcia9544502015-08-14 08:24:29 +02002960 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002961
Michal Vasko6c629ac2016-02-15 14:08:23 +01002962 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002963 goto error;
2964 }
2965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002967 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2968 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002969 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002970 continue;
2971 }
2972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 if (!strcmp(sub->name, "mandatory")) {
2974 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01002975 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002976 goto error;
2977 }
2978 /* just checking the flags in leaf is not sufficient, we would allow
2979 * multiple mandatory statements with the "false" value
2980 */
2981 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 GETVAL(value, sub, "value");
2984 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002985 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002986 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002987 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002988 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01002989 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 goto error;
2991 }
2992 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002993 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002994 } else if (!strcmp(sub->name, "when")) {
2995 if (anyxml->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01002996 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002997 goto error;
2998 }
2999
3000 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003001 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003002 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003003 goto error;
3004 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003005 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 } else if (!strcmp(sub->name, "must")) {
3007 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003008 } else if (!strcmp(sub->name, "if-feature")) {
3009 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003012 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 }
3015 }
Radek Krejci863c2852015-06-03 15:47:11 +02003016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 /* middle part - process nodes with cardinality of 0..n */
3018 if (c_must) {
3019 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003020 if (!anyxml->must) {
3021 LOGMEM;
3022 goto error;
3023 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003025 if (c_ftrs) {
3026 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003027 if (!anyxml->features) {
3028 LOGMEM;
3029 goto error;
3030 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003031 }
Radek Krejci863c2852015-06-03 15:47:11 +02003032
Radek Krejci73adb602015-07-02 18:07:40 +02003033 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003035 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3036 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 if (r) {
3038 goto error;
3039 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003040 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003041 r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003042 anyxml->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003043 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003044 goto error;
3045 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003046 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 }
Radek Krejci863c2852015-06-03 15:47:11 +02003048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003050
3051error:
3052
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003053 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003056}
3057
Michal Vasko0d343d12015-08-24 14:57:36 +02003058/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003059static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003060read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003061 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003062{
Radek Krejci76512572015-08-04 09:47:08 +02003063 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003064 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 struct lyxml_elem *sub, *next;
3066 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003067 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003068 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003071 if (!leaf) {
3072 LOGMEM;
3073 return NULL;
3074 }
Radek Krejci76512572015-08-04 09:47:08 +02003075 leaf->nodetype = LYS_LEAF;
3076 leaf->prev = (struct lys_node *)leaf;
3077 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003078
Michal Vaskoe0c59842015-09-24 13:52:20 +02003079 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3080 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 goto error;
3082 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003083
Radek Krejcia9544502015-08-14 08:24:29 +02003084 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003085
Michal Vasko6c629ac2016-02-15 14:08:23 +01003086 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003087 goto error;
3088 }
3089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003091 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3092 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003093 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003094 continue;
3095 }
3096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003097 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003098 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003099 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003100 goto error;
3101 }
Michal Vasko88c29542015-11-27 14:57:53 +01003102 /* HACK for unres */
3103 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003104 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003105 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3106 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 goto error;
3108 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003109 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003110 } else if (!strcmp(sub->name, "default")) {
3111 if (leaf->dflt) {
Radek Krejciadb57612016-02-16 13:34:34 +01003112 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003113 goto error;
3114 }
3115 GETVAL(value, sub, "value");
3116 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003117 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 } else if (!strcmp(sub->name, "units")) {
3119 if (leaf->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01003120 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 goto error;
3122 }
3123 GETVAL(value, sub, "name");
3124 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3125 } else if (!strcmp(sub->name, "mandatory")) {
3126 if (f_mand) {
Radek Krejciadb57612016-02-16 13:34:34 +01003127 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003128 goto error;
3129 }
3130 /* just checking the flags in leaf is not sufficient, we would allow
3131 * multiple mandatory statements with the "false" value
3132 */
3133 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 GETVAL(value, sub, "value");
3136 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003137 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003138 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003139 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003140 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003141 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 goto error;
3143 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003144 } else if (!strcmp(sub->name, "when")) {
3145 if (leaf->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003146 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003147 goto error;
3148 }
3149
3150 leaf->when = read_yin_when(module, sub);
3151 if (!leaf->when) {
3152 goto error;
3153 }
3154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003156 c_must++;
3157 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003158 } else if (!strcmp(sub->name, "if-feature")) {
3159 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003163 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003166
Michal Vasko88c29542015-11-27 14:57:53 +01003167 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003171 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003172 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 goto error;
3174 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003175 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003176 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003177 goto error;
3178 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 /* middle part - process nodes with cardinality of 0..n */
3182 if (c_must) {
3183 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003184 if (!leaf->must) {
3185 LOGMEM;
3186 goto error;
3187 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003189 if (c_ftrs) {
3190 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003191 if (!leaf->features) {
3192 LOGMEM;
3193 goto error;
3194 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003195 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003196
Radek Krejci73adb602015-07-02 18:07:40 +02003197 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003199 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3200 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 if (r) {
3202 goto error;
3203 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003204 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003205 r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003206 leaf->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003207 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003208 goto error;
3209 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003211 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003214
3215error:
3216
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003217 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003220}
3221
Michal Vasko0d343d12015-08-24 14:57:36 +02003222/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003223static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003224read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003225 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003226{
Radek Krejci76512572015-08-04 09:47:08 +02003227 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003228 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 struct lyxml_elem *sub, *next;
3230 const char *value;
3231 char *endptr;
3232 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003233 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003234 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003238 if (!llist) {
3239 LOGMEM;
3240 return NULL;
3241 }
Radek Krejci76512572015-08-04 09:47:08 +02003242 llist->nodetype = LYS_LEAFLIST;
3243 llist->prev = (struct lys_node *)llist;
3244 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003245
Michal Vaskoe0c59842015-09-24 13:52:20 +02003246 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3247 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003248 goto error;
3249 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003250
Radek Krejcia9544502015-08-14 08:24:29 +02003251 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003252
Michal Vasko6c629ac2016-02-15 14:08:23 +01003253 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003254 goto error;
3255 }
3256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003258 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3259 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003260 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003261 continue;
3262 }
3263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003265 if (has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003266 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 goto error;
3268 }
Michal Vasko88c29542015-11-27 14:57:53 +01003269 /* HACK for unres */
3270 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003271 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003272 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3273 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 goto error;
3275 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003276 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 } else if (!strcmp(sub->name, "units")) {
3278 if (llist->units) {
Radek Krejciadb57612016-02-16 13:34:34 +01003279 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 goto error;
3281 }
3282 GETVAL(value, sub, "name");
3283 llist->units = lydict_insert(module->ctx, value, strlen(value));
3284 } else if (!strcmp(sub->name, "ordered-by")) {
3285 if (f_ordr) {
Radek Krejciadb57612016-02-16 13:34:34 +01003286 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003287 goto error;
3288 }
3289 /* just checking the flags in llist is not sufficient, we would
3290 * allow multiple ordered-by statements with the "system" value
3291 */
3292 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003293
Radek Krejci1574a8d2015-08-03 14:16:52 +02003294 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003295 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3296 * state data
3297 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003298 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 continue;
3300 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 GETVAL(value, sub, "value");
3303 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003304 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 } else if (strcmp(value, "system")) {
Radek Krejciadb57612016-02-16 13:34:34 +01003306 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003308 } /* else system is the default value, so we can ignore it */
3309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 } else if (!strcmp(sub->name, "must")) {
3311 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003312 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003313 } else if (!strcmp(sub->name, "if-feature")) {
3314 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003315 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 } else if (!strcmp(sub->name, "min-elements")) {
3318 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01003319 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 goto error;
3321 }
3322 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 GETVAL(value, sub, "value");
3325 while (isspace(value[0])) {
3326 value++;
3327 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 /* convert it to uint32_t */
3330 errno = 0;
3331 endptr = NULL;
3332 val = strtoul(value, &endptr, 10);
3333 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003334 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 goto error;
3336 }
3337 llist->min = (uint32_t) val;
3338 } else if (!strcmp(sub->name, "max-elements")) {
3339 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003340 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 goto error;
3342 }
3343 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 GETVAL(value, sub, "value");
3346 while (isspace(value[0])) {
3347 value++;
3348 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003349
Radek Krejci0d7b2472016-02-12 11:11:03 +01003350 if (!strcmp(value, "unbounded")) {
3351 llist->max = 0;
3352 } else {
3353 /* convert it to uint32_t */
3354 errno = 0;
3355 endptr = NULL;
3356 val = strtoul(value, &endptr, 10);
3357 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003358 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003359 goto error;
3360 }
3361 llist->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003363 } else if (!strcmp(sub->name, "when")) {
3364 if (llist->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003365 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003366 goto error;
3367 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003368
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003369 llist->when = read_yin_when(module, sub);
3370 if (!llist->when) {
3371 goto error;
3372 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003374 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003377
Michal Vasko88c29542015-11-27 14:57:53 +01003378 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003381 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003382 if (!has_type) {
Radek Krejciadb57612016-02-16 13:34:34 +01003383 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 goto error;
3385 }
3386 if (llist->max && llist->min > llist->max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003387 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 goto error;
3389 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 /* middle part - process nodes with cardinality of 0..n */
3392 if (c_must) {
3393 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003394 if (!llist->must) {
3395 LOGMEM;
3396 goto error;
3397 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003399 if (c_ftrs) {
3400 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003401 if (!llist->features) {
3402 LOGMEM;
3403 goto error;
3404 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003405 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003406
Radek Krejci73adb602015-07-02 18:07:40 +02003407 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003409 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3410 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 if (r) {
3412 goto error;
3413 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003414 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003415 r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003416 llist->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003417 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003418 goto error;
3419 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003424
3425error:
3426
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003427 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003430}
3431
Michal Vasko0d343d12015-08-24 14:57:36 +02003432/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003433static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003434read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3435 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003436{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003437 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003438 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003440 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003441 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003443 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 char *auxs;
3445 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 /* init */
3448 memset(&root, 0, sizeof root);
3449 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003452 if (!list) {
3453 LOGMEM;
3454 return NULL;
3455 }
Radek Krejci76512572015-08-04 09:47:08 +02003456 list->nodetype = LYS_LIST;
3457 list->prev = (struct lys_node *)list;
3458 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003459
Michal Vaskoe0c59842015-09-24 13:52:20 +02003460 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3461 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 goto error;
3463 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003464
Radek Krejcia9544502015-08-14 08:24:29 +02003465 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 /* process list's specific children */
3468 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003469 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3470 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003471 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003472 continue;
3473 }
3474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 /* data statements */
3476 if (!strcmp(sub->name, "container") ||
3477 !strcmp(sub->name, "leaf-list") ||
3478 !strcmp(sub->name, "leaf") ||
3479 !strcmp(sub->name, "list") ||
3480 !strcmp(sub->name, "choice") ||
3481 !strcmp(sub->name, "uses") ||
3482 !strcmp(sub->name, "grouping") ||
3483 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003484 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003485 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003487 /* array counters */
3488 } else if (!strcmp(sub->name, "key")) {
3489 /* check cardinality 0..1 */
3490 if (list->keys_size) {
Radek Krejciadb57612016-02-16 13:34:34 +01003491 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 goto error;
3493 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 /* count the number of keys */
3496 GETVAL(value, sub, "value");
3497 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003498 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 while ((value = strpbrk(value, " \t\n"))) {
3500 list->keys_size++;
3501 while (isspace(*value)) {
3502 value++;
3503 }
3504 }
3505 list->keys_size++;
3506 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003507 if (!list->keys) {
3508 LOGMEM;
3509 goto error;
3510 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 } else if (!strcmp(sub->name, "unique")) {
3512 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003513 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003514 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003515 } else if (!strcmp(sub->name, "typedef")) {
3516 c_tpdf++;
3517 } else if (!strcmp(sub->name, "must")) {
3518 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003519 } else if (!strcmp(sub->name, "if-feature")) {
3520 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003522 /* optional stetments */
3523 } else if (!strcmp(sub->name, "ordered-by")) {
3524 if (f_ordr) {
Radek Krejciadb57612016-02-16 13:34:34 +01003525 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 goto error;
3527 }
3528 /* just checking the flags in llist is not sufficient, we would
3529 * allow multiple ordered-by statements with the "system" value
3530 */
3531 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003532
Radek Krejci1574a8d2015-08-03 14:16:52 +02003533 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3535 * state data
3536 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003537 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 continue;
3539 }
Radek Krejci345ad742015-06-03 11:04:18 +02003540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 GETVAL(value, sub, "value");
3542 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003543 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 } else if (strcmp(value, "system")) {
Radek Krejciadb57612016-02-16 13:34:34 +01003545 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 goto error;
3547 }
3548 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003549 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 } else if (!strcmp(sub->name, "min-elements")) {
3551 if (f_min) {
Radek Krejciadb57612016-02-16 13:34:34 +01003552 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 goto error;
3554 }
3555 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 GETVAL(value, sub, "value");
3558 while (isspace(value[0])) {
3559 value++;
3560 }
Radek Krejci345ad742015-06-03 11:04:18 +02003561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 /* convert it to uint32_t */
3563 errno = 0;
3564 auxs = NULL;
3565 val = strtoul(value, &auxs, 10);
3566 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003567 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 goto error;
3569 }
3570 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003571 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 } else if (!strcmp(sub->name, "max-elements")) {
3573 if (f_max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003574 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 goto error;
3576 }
3577 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003578
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 GETVAL(value, sub, "value");
3580 while (isspace(value[0])) {
3581 value++;
3582 }
Radek Krejci345ad742015-06-03 11:04:18 +02003583
Radek Krejci0d7b2472016-02-12 11:11:03 +01003584 if (!strcmp(value, "unbounded")) {
3585 list->max = 0;;
3586 } else {
3587 /* convert it to uint32_t */
3588 errno = 0;
3589 auxs = NULL;
3590 val = strtoul(value, &auxs, 10);
3591 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejciadb57612016-02-16 13:34:34 +01003592 LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_XML, sub, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003593 goto error;
3594 }
3595 list->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003597 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003598 } else if (!strcmp(sub->name, "when")) {
3599 if (list->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003600 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003601 goto error;
3602 }
3603
3604 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003605 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003606 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003607 goto error;
3608 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003609 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003610 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003611 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003612 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 }
3614 }
Radek Krejci345ad742015-06-03 11:04:18 +02003615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003617 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejciadb57612016-02-16 13:34:34 +01003618 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 goto error;
3620 }
3621 if (list->max && list->min > list->max) {
Radek Krejciadb57612016-02-16 13:34:34 +01003622 LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_XML, yin, "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 goto error;
3624 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3627 if (c_tpdf) {
3628 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003629 if (!list->tpdf) {
3630 LOGMEM;
3631 goto error;
3632 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003634 if (c_must) {
3635 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003636 if (!list->must) {
3637 LOGMEM;
3638 goto error;
3639 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003640 }
3641 if (c_ftrs) {
3642 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003643 if (!list->features) {
3644 LOGMEM;
3645 goto error;
3646 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003647 }
Radek Krejci73adb602015-07-02 18:07:40 +02003648 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003650 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3651 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 if (r) {
3653 goto error;
3654 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003655 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003656 r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003657 list->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003658 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003659 goto error;
3660 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003661 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003662 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3663 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003664 if (r) {
3665 goto error;
3666 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 }
3668 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003669
Michal Vasko6c629ac2016-02-15 14:08:23 +01003670 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003671 goto error;
3672 }
3673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003674 /* last part - process data nodes */
3675 LY_TREE_FOR_SAFE(root.child, next, sub) {
3676 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003677 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003678 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003679 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003681 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003683 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003684 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003685 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003687 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003689 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003691 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003692 } else {
3693 LOGINT;
3694 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003696 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 goto error;
3698 }
Radek Krejci73adb602015-07-02 18:07:40 +02003699
Michal Vasko345da0a2015-12-02 10:35:55 +01003700 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003702
Radek Krejci461efb92016-02-12 15:52:18 +01003703 if (key_str) {
3704 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
3705 goto error;
3706 }
3707 } /* 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 +02003708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 /* process unique statements */
3710 if (c_uniq) {
3711 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003712 if (!list->unique) {
3713 LOGMEM;
3714 goto error;
3715 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003716
Radek Krejci461efb92016-02-12 15:52:18 +01003717 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3718 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3719 list->unique_size++;
3720 if (r) {
3721 goto error;
3722 }
3723
3724 lyxml_free(module->ctx, sub);
3725 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003729
3730error:
3731
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003732 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003734 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003735 }
3736 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003737 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003741}
3742
Michal Vasko0d343d12015-08-24 14:57:36 +02003743/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003744static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003745read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3746 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003747{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003749 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003750 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003751 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 const char *value;
3753 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003754 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 /* init */
3757 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003760 if (!cont) {
3761 LOGMEM;
3762 return NULL;
3763 }
Radek Krejci76512572015-08-04 09:47:08 +02003764 cont->nodetype = LYS_CONTAINER;
3765 cont->prev = (struct lys_node *)cont;
3766 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003767
Michal Vaskoe0c59842015-09-24 13:52:20 +02003768 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3769 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 goto error;
3771 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003772
Radek Krejcia9544502015-08-14 08:24:29 +02003773 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003775 /* process container's specific children */
3776 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003777 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003778 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003779 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003780 continue;
3781 }
3782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 if (!strcmp(sub->name, "presence")) {
3784 if (cont->presence) {
Radek Krejciadb57612016-02-16 13:34:34 +01003785 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 goto error;
3787 }
3788 GETVAL(value, sub, "value");
3789 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003790
Michal Vasko345da0a2015-12-02 10:35:55 +01003791 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003792 } else if (!strcmp(sub->name, "when")) {
3793 if (cont->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01003794 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003795 goto error;
3796 }
3797
3798 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003799 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003800 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003801 goto error;
3802 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003803 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 /* data statements */
3806 } else if (!strcmp(sub->name, "container") ||
3807 !strcmp(sub->name, "leaf-list") ||
3808 !strcmp(sub->name, "leaf") ||
3809 !strcmp(sub->name, "list") ||
3810 !strcmp(sub->name, "choice") ||
3811 !strcmp(sub->name, "uses") ||
3812 !strcmp(sub->name, "grouping") ||
3813 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003814 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003815 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 /* array counters */
3818 } else if (!strcmp(sub->name, "typedef")) {
3819 c_tpdf++;
3820 } else if (!strcmp(sub->name, "must")) {
3821 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003822 } else if (!strcmp(sub->name, "if-feature")) {
3823 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003825 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 }
3828 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3831 if (c_tpdf) {
3832 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003833 if (!cont->tpdf) {
3834 LOGMEM;
3835 goto error;
3836 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 }
3838 if (c_must) {
3839 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003840 if (!cont->must) {
3841 LOGMEM;
3842 goto error;
3843 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003845 if (c_ftrs) {
3846 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003847 if (!cont->features) {
3848 LOGMEM;
3849 goto error;
3850 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003851 }
Radek Krejci800af702015-06-02 13:46:01 +02003852
Radek Krejci73adb602015-07-02 18:07:40 +02003853 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003855 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3856 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 if (r) {
3858 goto error;
3859 }
3860 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003861 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3862 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 if (r) {
3864 goto error;
3865 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003866 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01003867 r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003868 cont->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01003869 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003870 goto error;
3871 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003874
Michal Vasko6c629ac2016-02-15 14:08:23 +01003875 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003876 goto error;
3877 }
3878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879 /* last part - process data nodes */
3880 LY_TREE_FOR_SAFE(root.child, next, sub) {
3881 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003882 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003883 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003884 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003885 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003886 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003888 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003890 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003891 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003892 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003894 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003895 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003896 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003898 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 goto error;
3900 }
Radek Krejci73adb602015-07-02 18:07:40 +02003901
Michal Vasko345da0a2015-12-02 10:35:55 +01003902 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003903 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003906
3907error:
3908
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003909 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003910 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003911 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003915}
3916
Michal Vasko0d343d12015-08-24 14:57:36 +02003917/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003918static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003919read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003920 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003921{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003923 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003924 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003925 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 int r;
3927 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 /* init */
3930 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003933 if (!grp) {
3934 LOGMEM;
3935 return NULL;
3936 }
Radek Krejci76512572015-08-04 09:47:08 +02003937 grp->nodetype = LYS_GROUPING;
3938 grp->prev = (struct lys_node *)grp;
3939 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003940
Michal Vasko71e1aa82015-08-12 12:17:51 +02003941 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 goto error;
3943 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003944
Radek Krejcia9544502015-08-14 08:24:29 +02003945 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3946
Radek Krejci1d82ef62015-08-07 14:44:40 +02003947 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003948 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3949 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003950 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003951 continue;
3952 }
3953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003954 /* data statements */
3955 if (!strcmp(sub->name, "container") ||
3956 !strcmp(sub->name, "leaf-list") ||
3957 !strcmp(sub->name, "leaf") ||
3958 !strcmp(sub->name, "list") ||
3959 !strcmp(sub->name, "choice") ||
3960 !strcmp(sub->name, "uses") ||
3961 !strcmp(sub->name, "grouping") ||
3962 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003963 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003964 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 /* array counters */
3967 } else if (!strcmp(sub->name, "typedef")) {
3968 c_tpdf++;
3969 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01003970 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 goto error;
3972 }
3973 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3976 if (c_tpdf) {
3977 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003978 if (!grp->tpdf) {
3979 LOGMEM;
3980 goto error;
3981 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003982 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003983 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003984 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3985 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003986 if (r) {
3987 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003988 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003990
Michal Vasko6c629ac2016-02-15 14:08:23 +01003991 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003992 goto error;
3993 }
3994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003995 /* last part - process data nodes */
3996 LY_TREE_FOR_SAFE(root.child, next, sub) {
3997 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003998 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003999 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004000 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004002 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004004 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004006 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004007 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004008 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004010 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004011 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004012 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004013 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004014 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 goto error;
4016 }
Radek Krejci73adb602015-07-02 18:07:40 +02004017
Michal Vasko345da0a2015-12-02 10:35:55 +01004018 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004019 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004022
4023error:
4024
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004025 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004027 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004030 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004031}
4032
Michal Vasko0d343d12015-08-24 14:57:36 +02004033/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004034static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004035read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4036 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004037{
Radek Krejcie0674f82015-06-15 13:58:51 +02004038 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004039 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004040 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004041 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004042 int r;
4043 int c_tpdf = 0;
4044
Radek Krejcie0674f82015-06-15 13:58:51 +02004045 /* init */
4046 memset(&root, 0, sizeof root);
4047
Michal Vasko38d01f72015-06-15 09:41:06 +02004048 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004049 if (!inout) {
4050 LOGMEM;
4051 return NULL;
4052 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004053 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004054
4055 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004056 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004057 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004058 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004059 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004060 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004061 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004062 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004063 }
4064
Radek Krejci76512572015-08-04 09:47:08 +02004065 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004066
Radek Krejci6a113852015-07-03 16:04:20 +02004067 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004068 goto error;
4069 }
4070
Radek Krejcia9544502015-08-14 08:24:29 +02004071 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4072
Michal Vasko38d01f72015-06-15 09:41:06 +02004073 /* data statements */
4074 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004075 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4076 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004077 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004078 continue;
4079 }
4080
Michal Vasko38d01f72015-06-15 09:41:06 +02004081 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004082 !strcmp(sub->name, "leaf-list") ||
4083 !strcmp(sub->name, "leaf") ||
4084 !strcmp(sub->name, "list") ||
4085 !strcmp(sub->name, "choice") ||
4086 !strcmp(sub->name, "uses") ||
4087 !strcmp(sub->name, "grouping") ||
4088 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004089 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004090 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004092 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004093 } else if (!strcmp(sub->name, "typedef")) {
4094 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004095
Michal Vasko38d01f72015-06-15 09:41:06 +02004096 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004097 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004098 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004099 }
4100 }
4101
4102 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4103 if (c_tpdf) {
4104 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004105 if (!inout->tpdf) {
4106 LOGMEM;
4107 goto error;
4108 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004109 }
4110
Radek Krejci73adb602015-07-02 18:07:40 +02004111 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004112 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4113 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004114 if (r) {
4115 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004116 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004117 }
4118
Michal Vasko6c629ac2016-02-15 14:08:23 +01004119 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004120 goto error;
4121 }
4122
Michal Vasko38d01f72015-06-15 09:41:06 +02004123 /* last part - process data nodes */
4124 LY_TREE_FOR_SAFE(root.child, next, sub) {
4125 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004126 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004127 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004128 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004129 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004130 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004132 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004133 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004134 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004135 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004136 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004137 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004138 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004139 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004140 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004141 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004142 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004143 goto error;
4144 }
Radek Krejci73adb602015-07-02 18:07:40 +02004145
Michal Vasko345da0a2015-12-02 10:35:55 +01004146 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004147 }
4148
Michal Vasko38d01f72015-06-15 09:41:06 +02004149 return retval;
4150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004152
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004153 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004154 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004155 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004156 }
4157
4158 return NULL;
4159}
4160
Michal Vasko0d343d12015-08-24 14:57:36 +02004161/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004162static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004163read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4164 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004165{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004166 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004167 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004168 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004169 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004170 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004171 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004172
Michal Vaskoc6551b32015-06-16 10:51:43 +02004173 memset(&root, 0, sizeof root);
4174
Michal Vasko0ea41032015-06-16 08:53:55 +02004175 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004176 if (!notif) {
4177 LOGMEM;
4178 return NULL;
4179 }
Radek Krejci76512572015-08-04 09:47:08 +02004180 notif->nodetype = LYS_NOTIF;
4181 notif->prev = (struct lys_node *)notif;
4182 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004183
Radek Krejci6a113852015-07-03 16:04:20 +02004184 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004185 goto error;
4186 }
4187
Radek Krejcia9544502015-08-14 08:24:29 +02004188 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4189
Michal Vasko0ea41032015-06-16 08:53:55 +02004190 /* process rpc's specific children */
4191 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004192 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4193 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004194 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004195 continue;
4196 }
4197
Michal Vasko0ea41032015-06-16 08:53:55 +02004198 /* data statements */
4199 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004200 !strcmp(sub->name, "leaf-list") ||
4201 !strcmp(sub->name, "leaf") ||
4202 !strcmp(sub->name, "list") ||
4203 !strcmp(sub->name, "choice") ||
4204 !strcmp(sub->name, "uses") ||
4205 !strcmp(sub->name, "grouping") ||
4206 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004207 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004208 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004210 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004211 } else if (!strcmp(sub->name, "typedef")) {
4212 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004213 } else if (!strcmp(sub->name, "if-feature")) {
4214 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004215 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004216 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004217 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004218 }
4219 }
4220
4221 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4222 if (c_tpdf) {
4223 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004224 if (!notif->tpdf) {
4225 LOGMEM;
4226 goto error;
4227 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004228 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004229 if (c_ftrs) {
4230 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004231 if (!notif->features) {
4232 LOGMEM;
4233 goto error;
4234 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004235 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004236
Radek Krejci73adb602015-07-02 18:07:40 +02004237 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004238 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004239 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4240 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004241 if (r) {
4242 goto error;
4243 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004244 } else if (!strcmp(sub->name, "if-features")) {
Michal Vasko217db072016-02-15 12:32:04 +01004245 r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004246 notif->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01004247 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004248 goto error;
4249 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004251 }
4252
Michal Vasko6c629ac2016-02-15 14:08:23 +01004253 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004254 goto error;
4255 }
4256
Michal Vasko0ea41032015-06-16 08:53:55 +02004257 /* last part - process data nodes */
4258 LY_TREE_FOR_SAFE(root.child, next, sub) {
4259 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004260 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004261 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004262 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004263 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004264 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004266 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004267 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004268 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004269 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004270 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004271 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004272 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004273 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004274 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004275 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004276 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004277 goto error;
4278 }
Radek Krejci73adb602015-07-02 18:07:40 +02004279
Michal Vasko345da0a2015-12-02 10:35:55 +01004280 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004281 }
4282
Michal Vasko0ea41032015-06-16 08:53:55 +02004283 return retval;
4284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004286
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004287 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004288 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004289 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004290 }
4291
4292 return NULL;
4293}
4294
Michal Vasko0d343d12015-08-24 14:57:36 +02004295/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004296static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004297read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4298 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004299{
Radek Krejcie0674f82015-06-15 13:58:51 +02004300 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004301 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004302 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004303 struct lys_node_rpc *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004304 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004305 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004306
Radek Krejcie0674f82015-06-15 13:58:51 +02004307 /* init */
4308 memset(&root, 0, sizeof root);
4309
Michal Vasko38d01f72015-06-15 09:41:06 +02004310 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004311 if (!rpc) {
4312 LOGMEM;
4313 return NULL;
4314 }
Radek Krejci76512572015-08-04 09:47:08 +02004315 rpc->nodetype = LYS_RPC;
4316 rpc->prev = (struct lys_node *)rpc;
4317 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004318
Radek Krejci6a113852015-07-03 16:04:20 +02004319 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004320 goto error;
4321 }
4322
Radek Krejcia9544502015-08-14 08:24:29 +02004323 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4324
Michal Vasko38d01f72015-06-15 09:41:06 +02004325 /* process rpc's specific children */
4326 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004327 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4328 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004329 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004330 continue;
4331 }
4332
Michal Vasko38d01f72015-06-15 09:41:06 +02004333 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004335 && (rpc->child->nodetype == LYS_INPUT
4336 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004337 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004338 goto error;
4339 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004340 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004341 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004342 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004343 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004344 && (rpc->child->nodetype == LYS_INPUT
4345 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004346 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004347 goto error;
4348 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004349 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004350 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004353 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004354 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004355 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004358 } else if (!strcmp(sub->name, "typedef")) {
4359 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004360 } else if (!strcmp(sub->name, "if-feature")) {
4361 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004362 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004363 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004364 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004365 }
4366 }
4367
4368 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4369 if (c_tpdf) {
4370 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004371 if (!rpc->tpdf) {
4372 LOGMEM;
4373 goto error;
4374 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004375 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004376 if (c_ftrs) {
4377 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004378 if (!rpc->features) {
4379 LOGMEM;
4380 goto error;
4381 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004382 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004383
Radek Krejci73adb602015-07-02 18:07:40 +02004384 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004385 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004386 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4387 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004388 if (r) {
4389 goto error;
4390 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004391 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01004392 r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004393 rpc->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01004394 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004395 goto error;
4396 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004397 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004398 }
4399
Michal Vasko6c629ac2016-02-15 14:08:23 +01004400 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004401 goto error;
4402 }
4403
Michal Vasko38d01f72015-06-15 09:41:06 +02004404 /* last part - process data nodes */
4405 LY_TREE_FOR_SAFE(root.child, next, sub) {
4406 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004407 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004408 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004409 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004410 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004411 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004412 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004413 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004414 goto error;
4415 }
Radek Krejci73adb602015-07-02 18:07:40 +02004416
Michal Vasko345da0a2015-12-02 10:35:55 +01004417 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004418 }
4419
Michal Vasko38d01f72015-06-15 09:41:06 +02004420 return retval;
4421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004423
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004424 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004425 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004426 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004427 }
4428
4429 return NULL;
4430}
4431
Michal Vasko0d343d12015-08-24 14:57:36 +02004432/* logs directly
4433 *
Radek Krejci74705112015-06-05 10:25:44 +02004434 * resolve - referenced grouping should be bounded to the namespace (resolved)
4435 * only when uses does not appear in grouping. In a case of grouping's uses,
4436 * we just get information but we do not apply augment or refine to it.
4437 */
Radek Krejci76512572015-08-04 09:47:08 +02004438static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004439read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004440 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004441{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004442 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004443 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004444 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004446 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004449 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004450 if (!uses) {
4451 LOGMEM;
4452 return NULL;
4453 }
Radek Krejci76512572015-08-04 09:47:08 +02004454 uses->nodetype = LYS_USES;
4455 uses->prev = (struct lys_node *)uses;
4456 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004457
Radek Krejcia9544502015-08-14 08:24:29 +02004458 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004460
Michal Vaskoe0c59842015-09-24 13:52:20 +02004461 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4462 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 goto error;
4464 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004465
Radek Krejcia9544502015-08-14 08:24:29 +02004466 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004469 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004470 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4471 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004472 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004473 continue;
4474 }
4475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 if (!strcmp(sub->name, "refine")) {
4477 c_ref++;
4478 } else if (!strcmp(sub->name, "augment")) {
4479 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004480 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004481 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004482 } else if (!strcmp(sub->name, "when")) {
4483 if (uses->when) {
Radek Krejciadb57612016-02-16 13:34:34 +01004484 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_XML, sub, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004485 goto error;
4486 }
4487
4488 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004489 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004490 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004491 goto error;
4492 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004493 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004495 LOGVAL(LYE_INSTMT, LOGLINE(sub), LY_VLOG_XML, sub, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 }
4498 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 /* process properties with cardinality 0..n */
4501 if (c_ref) {
4502 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004503 if (!uses->refine) {
4504 LOGMEM;
4505 goto error;
4506 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 }
4508 if (c_aug) {
4509 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004510 if (!uses->augment) {
4511 LOGMEM;
4512 goto error;
4513 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004515 if (c_ftrs) {
4516 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004517 if (!uses->features) {
4518 LOGMEM;
4519 goto error;
4520 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004521 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004522
Michal Vasko6c629ac2016-02-15 14:08:23 +01004523 if (lys_node_addchild(parent, lys_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004524 goto error;
4525 }
4526
Radek Krejcia9544502015-08-14 08:24:29 +02004527 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004529 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4530 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004531 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004532 goto error;
4533 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004534 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004535 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4536 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004537 if (r) {
4538 goto error;
4539 }
4540 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko217db072016-02-15 12:32:04 +01004541 r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004542 uses->features_size++;
Michal Vasko217db072016-02-15 12:32:04 +01004543 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004544 goto error;
4545 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 }
4547 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004548
Michal Vasko0bd29d12015-08-19 11:45:49 +02004549 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004550 goto error;
4551 }
Radek Krejci74705112015-06-05 10:25:44 +02004552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004553 if (resolve) {
4554 /* inherit config flag */
4555 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004556 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004557 } else {
4558 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004559 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 }
4561 }
Radek Krejcib388c152015-06-04 17:03:03 +02004562
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004564
4565error:
4566
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004567 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004570}
4571
Michal Vasko0d343d12015-08-24 14:57:36 +02004572/* logs directly
4573 *
4574 * common code for yin_read_module() and yin_read_submodule()
4575 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576static int
Radek Krejcic071c542016-01-27 14:57:51 +01004577read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4578 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004579{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004581 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004582 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004583 struct lys_module *trg;
4584 struct lys_import *aux_imp;
4585 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004587 int i, j, r;
4588 int inc_size_aux = 0;
4589 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004590 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004591 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 +02004592
Radek Krejcic071c542016-01-27 14:57:51 +01004593 /* to simplify code, store the module/submodule being processed as trg */
4594 trg = submodule ? (struct lys_module*)submodule : module;
4595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 /* init */
4597 memset(&root, 0, sizeof root);
4598 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004599 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 /*
4602 * in the first run, we process elements with cardinality of 1 or 0..1 and
4603 * count elements with cardinality 0..n. Data elements (choices, containers,
4604 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4605 * need have all top-level and groupings already prepared at that time. In
4606 * the middle loop, we process other elements with carinality of 0..n since
4607 * we need to allocate arrays to store them.
4608 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004609 LY_TREE_FOR_SAFE(yin->child, next, child) {
4610 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004611 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004612 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 continue;
4614 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004615
Radek Krejcic071c542016-01-27 14:57:51 +01004616 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 if (module->ns) {
Radek Krejciadb57612016-02-16 13:34:34 +01004618 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 goto error;
4620 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004621 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004623 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004624 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 if (module->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004626 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004627 goto error;
4628 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004630 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004631 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 goto error;
4633 }
4634 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004635 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004636 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4637 if (submodule->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004638 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004639 goto error;
4640 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004641 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 if (value != submodule->belongsto->name) {
Radek Krejciadb57612016-02-16 13:34:34 +01004643 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 goto error;
4645 }
Radek Krejcif3886932015-06-04 17:36:06 +02004646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004648 if (!child->child) {
Radek Krejciadb57612016-02-16 13:34:34 +01004649 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), LY_VLOG_XML, child, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejciadb57612016-02-16 13:34:34 +01004652 LOGVAL(LYE_INSTMT, LOGLINE(child->child), LY_VLOG_XML, child->child, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004654 } else if (child->child->next) {
Radek Krejciadb57612016-02-16 13:34:34 +01004655 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), LY_VLOG_XML, child->child->next,
4656 child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 goto error;
4658 }
4659 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004660 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 /* check here differs from a generic prefix check, since this prefix
4662 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004663 */
Radek Krejcic6556022016-01-27 15:16:45 +01004664 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004665 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child->child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004666 goto error;
4667 }
Radek Krejcic071c542016-01-27 14:57:51 +01004668 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004670 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004671 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004672
4673 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004674 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004675 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004676 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004678 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004682 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004684 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004685 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004686 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004687 lyxml_unlink_elem(ctx, child, 2);
4688 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004689
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004691 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004692 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004693 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004696 } else if (!strcmp(child->name, "container") ||
4697 !strcmp(child->name, "leaf-list") ||
4698 !strcmp(child->name, "leaf") ||
4699 !strcmp(child->name, "list") ||
4700 !strcmp(child->name, "choice") ||
4701 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004702 !strcmp(child->name, "anyxml") ||
4703 !strcmp(child->name, "rpc") ||
4704 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004705 lyxml_unlink_elem(ctx, child, 2);
4706 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004707
Radek Krejci1d82ef62015-08-07 14:44:40 +02004708 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004710 lyxml_unlink_elem(ctx, child, 2);
4711 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004714 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004715 if (trg->dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01004716 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004717 goto error;
4718 }
Radek Krejcic071c542016-01-27 14:57:51 +01004719 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004720 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004721 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 goto error;
4723 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004724 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004725 if (trg->ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01004726 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
Radek Krejcic071c542016-01-27 14:57:51 +01004729 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004730 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004731 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 goto error;
4733 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004734 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004735 if (trg->org) {
Radek Krejciadb57612016-02-16 13:34:34 +01004736 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 goto error;
4738 }
Radek Krejcic071c542016-01-27 14:57:51 +01004739 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004740 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004741 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 goto error;
4743 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004744 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004745 if (trg->contact) {
Radek Krejciadb57612016-02-16 13:34:34 +01004746 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 goto error;
4748 }
Radek Krejcic071c542016-01-27 14:57:51 +01004749 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004750 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004751 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 goto error;
4753 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004754 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004755 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004756 if (version_flag) {
Radek Krejciadb57612016-02-16 13:34:34 +01004757 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 goto error;
4759 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004760 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 if (strcmp(value, "1")) {
Radek Krejciadb57612016-02-16 13:34:34 +01004762 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004763 goto error;
4764 }
Radek Krejcic071c542016-01-27 14:57:51 +01004765 version_flag = 1;
4766 if (!submodule) {
4767 module->version = 1;
4768 } /* 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 +01004769 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004770
Radek Krejci1d82ef62015-08-07 14:44:40 +02004771 } else if (!strcmp(child->name, "extension")) {
4772 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004773
Radek Krejci3d468122015-10-02 13:36:12 +02004774 /* we have the following supported (hardcoded) extensions: */
4775 /* ietf-netconf's get-filter-element-attributes */
4776 if (!strcmp(module->ns, LY_NSNC) &&
4777 !strcmp(value, "get-filter-element-attributes")) {
4778 LOGDBG("NETCONF filter extension found");
4779 /* NACM's default-deny-write and default-deny-all */
4780 } else if (!strcmp(module->ns, LY_NSNACM) &&
4781 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4782 LOGDBG("NACM extension found");
4783 /* other extensions are not supported, so inform about such an extension */
4784 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004785 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004786 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004787 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004788 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004789 LOGVAL(LYE_INSTMT, LOGLINE(child), LY_VLOG_XML, child, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004790 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 }
4792 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004793
Radek Krejcic071c542016-01-27 14:57:51 +01004794 /* check for mandatory statements */
4795 if (submodule && !submodule->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004796 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004797 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004798 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 if (!module->ns) {
Radek Krejciadb57612016-02-16 13:34:34 +01004800 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 goto error;
4802 }
4803 if (!module->prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01004804 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004805 goto error;
4806 }
4807 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 /* allocate arrays for elements with cardinality of 0..n */
4810 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004811 trg->imp = calloc(c_imp, sizeof *trg->imp);
4812 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004813 LOGMEM;
4814 goto error;
4815 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 }
4817 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004818 trg->rev = calloc(c_rev, sizeof *trg->rev);
4819 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004820 LOGMEM;
4821 goto error;
4822 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004823 }
4824 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004825 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4826 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004827 LOGMEM;
4828 goto error;
4829 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 }
4831 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004832 trg->ident = calloc(c_ident, sizeof *trg->ident);
4833 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004834 LOGMEM;
4835 goto error;
4836 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837 }
4838 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004839 trg->inc = calloc(c_inc, sizeof *trg->inc);
4840 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004841 LOGMEM;
4842 goto error;
4843 }
Radek Krejcic071c542016-01-27 14:57:51 +01004844 trg->inc_size = c_inc;
4845 /* trg->inc_size can be updated by the included submodules,
4846 * so we will use inc_size_aux here, trg->inc_size stores the
4847 * target size of the array
4848 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004850 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004851 trg->augment = calloc(c_aug, sizeof *trg->augment);
4852 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004853 LOGMEM;
4854 goto error;
4855 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004856 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004857 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004858 trg->features = calloc(c_ftrs, sizeof *trg->features);
4859 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004860 LOGMEM;
4861 goto error;
4862 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004863 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004864 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004865 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4866 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004867 LOGMEM;
4868 goto error;
4869 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004870 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004871
Michal Vasko2f7925f2015-10-21 15:06:56 +02004872 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4873 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004874 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004875 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4876 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 if (r) {
4878 goto error;
4879 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004882 for (i = 0; i < trg->imp_size - 1; i++) {
4883 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004884 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 +02004885 goto error;
4886 }
4887 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004888
Radek Krejci1d82ef62015-08-07 14:44:40 +02004889 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004890 memset(&inc, 0, sizeof inc);
4891 /* 1) pass module, not trg, since we want to pass the main module
4892 * 2) we cannot pass directly the structure in the array since
4893 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004894 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004895 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4896 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 if (r) {
4898 goto error;
4899 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004902 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004903 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 +01004904 LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_XML, child, "Including submodule \"%s\" repeatedly.",
Michal Vasko27ab8222016-02-12 09:33:52 +01004905 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 goto error;
4907 }
4908 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004909
Radek Krejci1d82ef62015-08-07 14:44:40 +02004910 } else if (!strcmp(child->name, "revision")) {
4911 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004912 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejciadb57612016-02-16 13:34:34 +01004913 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004914 goto error;
4915 }
Radek Krejcic071c542016-01-27 14:57:51 +01004916 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004918 for (i = 0; i < trg->rev_size; i++) {
4919 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejciadb57612016-02-16 13:34:34 +01004920 LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_XML, child, value, child->name);
4921 LOGVAL(LYE_SPEC, 0, 0, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004922 }
4923 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004924
Radek Krejci1d82ef62015-08-07 14:44:40 +02004925 LY_TREE_FOR(child->child, child2) {
4926 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004927 if (trg->rev[trg->rev_size].dsc) {
Radek Krejciadb57612016-02-16 13:34:34 +01004928 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 goto error;
4930 }
Radek Krejcic071c542016-01-27 14:57:51 +01004931 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4932 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 goto error;
4934 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004935 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004936 if (trg->rev[trg->rev_size].ref) {
Radek Krejciadb57612016-02-16 13:34:34 +01004937 LOGVAL(LYE_TOOMANY, LOGLINE(child), LY_VLOG_XML, child, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004938 goto error;
4939 }
Radek Krejcic071c542016-01-27 14:57:51 +01004940 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4941 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 goto error;
4943 }
4944 } else {
Radek Krejciadb57612016-02-16 13:34:34 +01004945 LOGVAL(LYE_INSTMT, LOGLINE(child2), LY_VLOG_XML, child2, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946 goto error;
4947 }
4948 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004950 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004951 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004953 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004954 if (!value) {
4955 LOGMEM;
4956 goto error;
4957 }
Radek Krejcic071c542016-01-27 14:57:51 +01004958 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4959 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004960 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004961
Radek Krejcic071c542016-01-27 14:57:51 +01004962 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
4963 value = trg->rev[0].dsc;
4964 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4965 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004967
Radek Krejcic071c542016-01-27 14:57:51 +01004968 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
4969 value = trg->rev[0].ref;
4970 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4971 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004972 }
4973 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004974
Radek Krejcic071c542016-01-27 14:57:51 +01004975 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004976
Radek Krejci1d82ef62015-08-07 14:44:40 +02004977 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004978 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4979 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004980 if (r) {
4981 goto error;
4982 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004983
Radek Krejci1d82ef62015-08-07 14:44:40 +02004984 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004985 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4986 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 if (r) {
4988 goto error;
4989 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004990
Radek Krejci1d82ef62015-08-07 14:44:40 +02004991 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004992 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4993 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004994 if (r) {
4995 goto error;
4996 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004997
Radek Krejci1d82ef62015-08-07 14:44:40 +02004998 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004999 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5000 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005001 if (r) {
5002 goto error;
5003 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005004 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5005 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005009
Radek Krejcic071c542016-01-27 14:57:51 +01005010 if (submodule) {
5011 /* propagate imports into the main module */
5012 for (i = r = 0; i < submodule->imp_size; i++) {
5013 for (j = 0; j < module->imp_size; j++) {
5014 if (submodule->imp[i].module == module->imp[j].module &&
5015 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5016 /* check prefix match */
5017 if (submodule->imp[i].prefix != module->imp[j].prefix) {
Radek Krejciadb57612016-02-16 13:34:34 +01005018 LOGVAL(LYE_INID, LOGLINE(yin), LY_VLOG_XML, yin, submodule->imp[i].prefix,
Radek Krejcic071c542016-01-27 14:57:51 +01005019 "non-matching prefixes of imported module in main module and submodule");
5020 goto error;
5021 }
5022 break;
5023 }
5024 }
5025 if (j == module->imp_size) {
5026 /* new import */
5027 r++;
5028 }
5029 }
5030 if (r) {
5031 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5032 if (!aux_imp) {
5033 LOGMEM;
5034 goto error;
5035 }
5036 module->imp = aux_imp;
5037 for (i = r = 0; i < submodule->imp_size; i++) {
5038 for (j = 0; j < module->imp_size; j++) {
5039 if (submodule->imp[i].module == module->imp[j].module) {
5040 break;
5041 }
5042 }
5043 if (j == module->imp_size) {
5044 /* new import */
5045 /* check prefix uniqueness */
5046 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005047 LOGVAL(LYE_DUPID, LOGLINE(yin), LY_VLOG_XML, yin, "prefix", submodule->imp[i].prefix);
Radek Krejcic071c542016-01-27 14:57:51 +01005048 goto error;
5049 }
5050 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5051 module->imp[module->imp_size + r].external = 1;
5052 r++;
5053 }
5054 }
5055 module->imp_size += r;
5056 }
5057
Michal Vaskoe2905632016-02-11 15:42:24 +01005058 /* propagate includes into the main module */
Radek Krejcic071c542016-01-27 14:57:51 +01005059 for (i = r = 0; i < submodule->inc_size; i++) {
5060 for (j = 0; j < module->inc_size; j++) {
5061 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5062 break;
5063 }
5064 }
5065 if (j == module->inc_size) {
5066 /* new include */
5067 r++;
5068 }
5069 }
5070
5071 if (r) {
5072 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5073 if (!aux_inc) {
5074 LOGMEM;
5075 goto error;
5076 }
5077 module->inc = aux_inc;
5078 for (i = r = 0; i < submodule->inc_size; i++) {
5079 for (j = 0; j < module->inc_size; j++) {
5080 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5081 break;
5082 }
5083 }
5084 if (j == module->inc_size) {
5085 /* new include */
5086 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5087 module->inc[module->inc_size + r].external = 1;
5088 r++;
5089 }
5090 }
5091 module->inc_size += r;
5092 }
5093 }
5094
Radek Krejcif5be10f2015-06-16 13:29:36 +02005095 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005096 * refer to them. Submodule's data nodes are stored in the
5097 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005098 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005099 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005100 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005101 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005102 goto error;
5103 }
Radek Krejci74705112015-06-05 10:25:44 +02005104
Michal Vasko345da0a2015-12-02 10:35:55 +01005105 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 }
Radek Krejci74705112015-06-05 10:25:44 +02005107
Radek Krejcif5be10f2015-06-16 13:29:36 +02005108 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005109 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005110
Radek Krejci1d82ef62015-08-07 14:44:40 +02005111 if (!strcmp(child->name, "container")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005112 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005113 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005114 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005115 } else if (!strcmp(child->name, "leaf")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005116 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005117 } else if (!strcmp(child->name, "list")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005118 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005119 } else if (!strcmp(child->name, "choice")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005120 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005121 } else if (!strcmp(child->name, "uses")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005122 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005123 } else if (!strcmp(child->name, "anyxml")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005124 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005125 } else if (!strcmp(child->name, "rpc")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005126 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005127 } else if (!strcmp(child->name, "notification")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005128 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005129 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005130 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 goto error;
5132 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005133
Michal Vasko345da0a2015-12-02 10:35:55 +01005134 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005136
Michal Vasko2f7925f2015-10-21 15:06:56 +02005137 /* ... and finally augments (last, so we can augment our data, for instance) */
5138 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005139 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5140 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005141
Michal Vasko2f7925f2015-10-21 15:06:56 +02005142 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005143 goto error;
5144 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005145 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005146 }
5147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005148 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005149
5150error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 /* cleanup */
5152 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005153 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005154 }
5155 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005156 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005157 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005158 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005159 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005160 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005162 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005163}
5164
Michal Vasko0d343d12015-08-24 14:57:36 +02005165/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005166struct lys_submodule *
5167yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005168{
Michal Vasko9f258e42016-02-11 11:36:27 +01005169 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005170 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005171 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005173 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005174
Michal Vasko5a721fd2016-02-16 12:16:48 +01005175 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005176
Radek Krejci722b0072016-02-01 17:09:45 +01005177 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005178 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005179 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005180 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005182 /* check root element */
5183 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejciadb57612016-02-16 13:34:34 +01005184 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 goto error;
5186 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005189 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005190 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005191 goto error;
5192 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005193
Michal Vasko5a721fd2016-02-16 12:16:48 +01005194 submodule = calloc(1, sizeof *submodule);
5195 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005196 LOGMEM;
5197 goto error;
5198 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005199
Michal Vasko5a721fd2016-02-16 12:16:48 +01005200 submodule->ctx = module->ctx;
5201 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5202 submodule->type = 1;
5203 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005204
Michal Vasko5a721fd2016-02-16 12:16:48 +01005205 LOGVRB("Reading submodule \"%s\".", submodule->name);
5206 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 goto error;
5208 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005210 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005211 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005212
Michal Vasko5a721fd2016-02-16 12:16:48 +01005213 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005214
Michal Vasko5a721fd2016-02-16 12:16:48 +01005215 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005216
5217error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005218 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005219 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005220 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005221
Michal Vasko5a721fd2016-02-16 12:16:48 +01005222 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005223 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005224 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005225 }
5226
Michal Vasko5a721fd2016-02-16 12:16:48 +01005227 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005228
Michal Vasko9f258e42016-02-11 11:36:27 +01005229 /* warn about applied deviations */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005230 for (i = 0; i < submodule->deviation_size; ++i) {
5231 if (submodule->deviation[i].target_module) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005232 LOGERR(ly_errno, "Submodule parsing failed, but successfully deviated %smodule \"%s\".",
Michal Vasko5a721fd2016-02-16 12:16:48 +01005233 (submodule->deviation[i].target_module->type ? "sub" : ""),
5234 submodule->deviation[i].target_module->name);
Michal Vasko9f258e42016-02-11 11:36:27 +01005235 }
5236 }
5237
5238 /* remove applied augments */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005239 for (i = 0; i < submodule->augment_size; ++i) {
5240 if (submodule->augment[i].target) {
5241 LY_TREE_FOR_SAFE(submodule->augment[i].target->child, next, elem) {
5242 if (elem->parent == (struct lys_node *)&submodule->augment[i]) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005243 lys_node_free(elem, NULL, 0);
Michal Vasko9f258e42016-02-11 11:36:27 +01005244 }
5245 }
5246 }
5247 }
5248
Michal Vasko5a721fd2016-02-16 12:16:48 +01005249 lys_submodule_free(submodule, NULL);
5250
5251 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005252}
5253
Michal Vasko0d343d12015-08-24 14:57:36 +02005254/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005255struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005256yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005257{
Michal Vasko9f258e42016-02-11 11:36:27 +01005258 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005260 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005261 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005262 const char *value;
5263 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005264
Radek Krejcic071c542016-01-27 14:57:51 +01005265 unres = calloc(1, sizeof *unres);
5266 if (!unres) {
5267 LOGMEM;
5268 return NULL;
5269 }
5270
Radek Krejci722b0072016-02-01 17:09:45 +01005271 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005273 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005276 /* check root element */
5277 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejciadb57612016-02-16 13:34:34 +01005278 LOGVAL(LYE_INSTMT, LOGLINE(yin), LY_VLOG_XML, yin, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 goto error;
5280 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005282 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005283 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejciadb57612016-02-16 13:34:34 +01005284 LOGVAL(LYE_PATH, 0, LY_VLOG_XML, yin);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 goto error;
5286 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005288 module = calloc(1, sizeof *module);
5289 if (!module) {
5290 LOGMEM;
5291 goto error;
5292 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005294 module->ctx = ctx;
5295 module->name = lydict_insert(ctx, value, strlen(value));
5296 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005297 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005298
Michal Vasko9f258e42016-02-11 11:36:27 +01005299 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005300 if (read_sub_module(module, NULL, yin, unres)) {
5301 goto error;
5302 }
5303
5304 /* resolve rest of unres items */
5305 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005306 goto error;
5307 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005309 /* add to the context's list of modules */
5310 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005311 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 if (!newlist) {
5313 LOGMEM;
5314 goto error;
5315 }
5316 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5317 newlist[i] = NULL;
5318 }
5319 ctx->models.size *= 2;
5320 ctx->models.list = newlist;
5321 }
5322 for (i = 0; ctx->models.list[i]; i++) {
5323 /* check name (name/revision) and namespace uniqueness */
5324 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005325 if (ctx->models.list[i]->rev_size == module->rev_size) {
5326 /* both have the same number of revisions */
5327 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5328 /* both have the same revision -> we already have the same module */
5329 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005330 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005331
Michal Vasko9f258e42016-02-11 11:36:27 +01005332 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005333 module = ctx->models.list[i];
5334 if (implement && !module->implemented) {
5335 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005336 }
Radek Krejcic071c542016-01-27 14:57:51 +01005337
5338 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005339 }
5340 }
Radek Krejcif647e612015-07-30 11:36:07 +02005341 /* else (both elses) keep searching, for now the caller is just adding
5342 * another revision of an already present schema
5343 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005345 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 ctx->models.list[i]->name, module->name, module->ns);
5347 goto error;
5348 }
5349 }
5350 ctx->models.list[i] = module;
5351 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005352 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005353
Radek Krejcic071c542016-01-27 14:57:51 +01005354success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005356 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005357 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005358
Michal Vasko9f258e42016-02-11 11:36:27 +01005359 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005361 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005362
5363error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005364 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005365 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005366 unres_schema_free(module, &unres);
5367
5368 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005369 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005370 return NULL;
5371 }
5372
5373 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005374
Michal Vasko9f258e42016-02-11 11:36:27 +01005375 /* warn about applied deviations */
5376 for (i = 0; i < module->deviation_size; ++i) {
Michal Vasko60f4b452016-02-12 11:02:55 +01005377 if (module->deviation[i].target_module) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005378 LOGERR(ly_errno, "Module parsing failed, but successfully deviated %smodule \"%s\".",
Michal Vasko60f4b452016-02-12 11:02:55 +01005379 (module->deviation[i].target_module->type ? "sub" : ""),
5380 module->deviation[i].target_module->name);
Michal Vasko9f258e42016-02-11 11:36:27 +01005381 }
5382 }
5383
5384 /* remove applied augments */
5385 for (i = 0; i < module->augment_size; ++i) {
5386 if (module->augment[i].target) {
5387 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5388 if (elem->parent == (struct lys_node *)&module->augment[i]) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005389 lys_node_free(elem, NULL, 0);
Michal Vasko9f258e42016-02-11 11:36:27 +01005390 }
5391 }
5392 }
5393 }
5394
5395 lys_free(module, NULL, 1);
5396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005398}