blob: cc41c46f9803d2059574dab0d1f344060f4533b9 [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 Krejcice7fb782015-05-29 16:52:34 +020043#define GETVAL(value, node, arg) \
Michal Vasko2d710f32016-02-05 12:29:21 +010044 value = lyxml_get_attr(node, arg, NULL); \
45 if (!value) { \
46 LOGVAL(LYE_MISSARG, LOGLINE(node), arg, node->name); \
47 goto error; \
48 }
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);
89 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
90 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 Vaskof02e3742015-08-05 16:27:02 +0200101fill_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 +0200102{
Radek Krejci73adb602015-07-02 18:07:40 +0200103 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200104 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100105 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200106
Michal Vasko4cfcd252015-08-03 14:31:10 +0200107 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100108 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200109
Radek Krejci76512572015-08-04 09:47:08 +0200110 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200111 return EXIT_FAILURE;
112 }
Radek Krejci04581c62015-05-22 21:24:00 +0200113
Radek Krejci73adb602015-07-02 18:07:40 +0200114 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200115 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
116 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200117 continue;
118 }
119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200120 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100121 if (base_flag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200122 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200123 return EXIT_FAILURE;
124 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100125 base_flag = 1;
126
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200127 GETVAL(value, node, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100128 value = transform_schema2json(module, value, LOGLINE(node));
129 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200130 return EXIT_FAILURE;
131 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100132
133 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
134 lydict_remove(module->ctx, value);
135 return EXIT_FAILURE;
136 }
137 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200138 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200139 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200140 return EXIT_FAILURE;
141 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200142 }
Radek Krejci04581c62015-05-22 21:24:00 +0200143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200144 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200145
146error:
147 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200148}
149
Michal Vasko0d343d12015-08-24 14:57:36 +0200150/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200151static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200152read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200153{
Radek Krejci73adb602015-07-02 18:07:40 +0200154 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200155 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200156
Radek Krejci73adb602015-07-02 18:07:40 +0200157 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200158 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
159 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200160 continue;
161 }
162
Radek Krejci41726f92015-06-19 13:11:05 +0200163 if (!strcmp(child->name, "description")) {
164 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200165 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200166 return EXIT_FAILURE;
167 }
168 restr->dsc = read_yin_subnode(ctx, child, "text");
169 if (!restr->dsc) {
170 return EXIT_FAILURE;
171 }
172 } else if (!strcmp(child->name, "reference")) {
173 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200174 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200175 return EXIT_FAILURE;
176 }
177 restr->ref = read_yin_subnode(ctx, child, "text");
178 if (!restr->ref) {
179 return EXIT_FAILURE;
180 }
181 } else if (!strcmp(child->name, "error-app-tag")) {
182 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200183 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200184 return EXIT_FAILURE;
185 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200186 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200187 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200188 } else if (!strcmp(child->name, "error-message")) {
189 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200190 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200191 return EXIT_FAILURE;
192 }
193 restr->emsg = read_yin_subnode(ctx, child, "value");
194 if (!restr->emsg) {
195 return EXIT_FAILURE;
196 }
197 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200198 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200199 return EXIT_FAILURE;
200 }
Radek Krejci41726f92015-06-19 13:11:05 +0200201 }
202
203 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200204
205error:
206 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200207}
208
Michal Vasko88c29542015-11-27 14:57:53 +0100209/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
210int
Radek Krejcib8048692015-08-05 13:36:34 +0200211fill_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 +0200212 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200213{
Michal Vasko1dca6882015-10-22 14:29:42 +0200214 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200215 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200216 struct lys_restr **restr;
217 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200218 pcre *precomp;
219 int i, j, rc, err_offset;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200220 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200221 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200222
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200223 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200224 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200225 if (!value) {
226 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200227 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200228
229 i = parse_identifier(value);
230 if (i < 1) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200231 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100232 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200233 goto error;
234 }
235 /* module name */
236 if (value[i]) {
237 type->module_name = lydict_insert(module->ctx, value, i);
238 value += i;
Michal Vasko534f8442015-10-21 13:25:49 +0200239 if ((value[0] != ':') || (parse_identifier(value + 1) < 1)) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200240 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[0], value);
Michal Vasko88c29542015-11-27 14:57:53 +0100241 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200242 goto error;
243 }
Michal Vasko534f8442015-10-21 13:25:49 +0200244 ++value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200245 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200246
Michal Vasko1dca6882015-10-22 14:29:42 +0200247 rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100248 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200249 if (rc == -1) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200250 LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200251 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100252
253 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200254 } else if (rc == EXIT_FAILURE) {
Michal Vasko88c29542015-11-27 14:57:53 +0100255 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200256 }
257 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200258
Radek Krejcicf509982015-12-15 09:22:44 +0100259 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100260 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejcicf509982015-12-15 09:22:44 +0100261 type->der->flags, type->der->module, type->der->name, LOGLINE(yin))) {
262 return -1;
263 }
264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200265 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200266 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200267 /* RFC 6020 9.7.4 - bit */
268
269 /* get bit specifications, at least one must be present */
270 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200271 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
272 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100273 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200274 continue;
275 }
276
Radek Krejci994b6f62015-06-18 16:47:27 +0200277 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200278 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200279 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100280 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200281 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200282 }
283 }
Radek Krejciac781922015-07-09 15:35:14 +0200284 if (!type->der->type.der && !type->info.bits.count) {
285 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200286 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200287 goto error;
288 }
Radek Krejciac781922015-07-09 15:35:14 +0200289 if (type->der->type.der && type->info.bits.count) {
290 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200291 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200292 goto error;
293 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200294
295 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100296 if (!type->info.bits.bit) {
297 LOGMEM;
298 goto error;
299 }
Radek Krejci73adb602015-07-02 18:07:40 +0200300 p = 0;
301 i = -1;
302 LY_TREE_FOR(yin->child, next) {
303 i++;
304
305 GETVAL(value, next, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100306 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100307 goto error;
308 }
309
Radek Krejci994b6f62015-06-18 16:47:27 +0200310 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200311 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200312 type->info.bits.count = i + 1;
313 goto error;
314 }
315
316 /* check the name uniqueness */
317 for (j = 0; j < i; j++) {
318 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200319 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200320 type->info.bits.count = i + 1;
321 goto error;
322 }
323 }
324
Radek Krejci0d70c372015-07-02 16:23:10 +0200325 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200326 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200327 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
328 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200329 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200330 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200331
Radek Krejci0d70c372015-07-02 16:23:10 +0200332 if (!strcmp(node->name, "position")) {
333 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200334 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200335
336 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200337 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200338 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200339 type->info.bits.count = i + 1;
340 goto error;
341 }
342 type->info.bits.bit[i].pos = (uint32_t)p_;
343
344 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200345 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200346 p = type->info.bits.bit[i].pos;
347 p++;
348 } else {
349 /* check that the value is unique */
350 for (j = 0; j < i; j++) {
351 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200352 LOGVAL(LYE_BITS_DUPVAL, LOGLINE(node), type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200353 type->info.bits.count = i + 1;
354 goto error;
355 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200356 }
357 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200358 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100359 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200360 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200361 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200362 }
363 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200364 /* assign value automatically */
365 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200366 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200367 type->info.bits.count = i + 1;
368 goto error;
369 }
370 type->info.bits.bit[i].pos = (uint32_t)p;
371 p++;
372 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200373
374 /* keep them ordered by position */
375 j = i;
376 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
377 /* switch them */
378 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
379 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
380 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
381 j--;
382 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200383 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200384 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200386 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200387 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200388 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200389 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
390 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200391 continue;
392 }
393
Radek Krejcif9401c32015-06-26 16:47:36 +0200394 if (!strcmp(node->name, "range")) {
395 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200396 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200397 goto error;
398 }
399
400 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200401 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200402 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200403 goto error;
404 }
405 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100406 if (!type->info.dec64.range) {
407 LOGMEM;
408 goto error;
409 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200410 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
411
412 /* get possible substatements */
413 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
414 goto error;
415 }
416 } else if (!strcmp(node->name, "fraction-digits")) {
417 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200418 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200419 goto error;
420 }
421 GETVAL(value, node, "value");
422 v = strtol(value, NULL, 10);
423
424 /* range check */
425 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200426 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200427 goto error;
428 }
429 type->info.dec64.dig = (uint8_t)v;
430 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200431 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200432 goto error;
433 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200434 }
435
436 /* mandatory sub-statement(s) check */
437 if (!type->info.dec64.dig && !type->der->type.der) {
438 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200439 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200440 goto error;
441 }
Radek Krejci7511f402015-07-10 09:56:30 +0200442 if (type->info.dec64.dig && type->der->type.der) {
443 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200444 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200445 goto error;
446 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200447 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200449 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200450 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200451
Radek Krejci994b6f62015-06-18 16:47:27 +0200452 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200453 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200454 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
455 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100456 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200457 continue;
458 }
459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200460 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200461 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200462 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100463 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200464 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200465 }
466 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200467 if (!type->der->type.der && !type->info.enums.count) {
468 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200469 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200470 goto error;
471 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200472 if (type->der->type.der && type->info.enums.count) {
473 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200474 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200475 goto error;
476 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200477
Radek Krejci1574a8d2015-08-03 14:16:52 +0200478 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100479 if (!type->info.enums.enm) {
480 LOGMEM;
481 goto error;
482 }
Radek Krejci73adb602015-07-02 18:07:40 +0200483 v = 0;
484 i = -1;
485 LY_TREE_FOR(yin->child, next) {
486 i++;
487
488 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100489 if (!value[0]) {
490 LOGVAL(LYE_SPEC, LOGLINE(next), "Enum name must not be empty.");
491 goto error;
492 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200493 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200494 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200495 type->info.enums.count = i + 1;
496 goto error;
497 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200500 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200502 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200503 type->info.enums.count = i + 1;
504 goto error;
505 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200507 /* check the name uniqueness */
508 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200509 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200510 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200511 type->info.enums.count = i + 1;
512 goto error;
513 }
514 }
Radek Krejci04581c62015-05-22 21:24:00 +0200515
Radek Krejci0d70c372015-07-02 16:23:10 +0200516 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200517 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200518 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
519 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200520 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200521 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200522
Radek Krejci0d70c372015-07-02 16:23:10 +0200523 if (!strcmp(node->name, "value")) {
524 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200525 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200526
527 /* range check */
528 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200529 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200530 type->info.enums.count = i + 1;
531 goto error;
532 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200533 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200534
535 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200536 if (type->info.enums.enm[i].value > v) {
537 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200538 v++;
539 } else {
540 /* check that the value is unique */
541 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200542 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200543 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200544 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200545 type->info.enums.count = i + 1;
546 goto error;
547 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200548 }
549 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200550 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100551 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200552 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200553 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200554 }
555 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200556 /* assign value automatically */
557 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200558 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200559 type->info.enums.count = i + 1;
560 goto error;
561 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200562 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200563 v++;
564 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200565 }
566 break;
567
568 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200569 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200570
571 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200572 LY_TREE_FOR_SAFE(yin->child, next, node) {
573 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
574 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100575 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200576 continue;
577 }
578
Michal Vaskoe29c6622015-11-27 15:02:31 +0100579 if (strcmp(node->name, "base")) {
580 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200581 goto error;
582 }
583 }
584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200586 if (type->der->type.der) {
587 /* this is just a derived type with no base specified/required */
588 break;
589 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200590 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 goto error;
592 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200593 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200594 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 goto error;
596 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200597 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100598 /* store in the JSON format */
599 value = transform_schema2json(module, value, LOGLINE(yin->child));
600 if (!value) {
601 goto error;
602 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200603 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200604 goto error;
605 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200606 break;
607
608 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200609 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200610 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200611 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
612 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200613 continue;
614 }
615
Radek Krejciaf351422015-06-19 14:49:38 +0200616 if (!strcmp(node->name, "require-instance")) {
617 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200618 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200619 goto error;
620 }
621 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200622 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200623 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200624 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200625 type->info.inst.req = -1;
626 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200627 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200628 goto error;
629 }
630 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200631 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200632 goto error;
633 }
Radek Krejciaf351422015-06-19 14:49:38 +0200634 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 break;
637
Radek Krejcif2860132015-06-20 12:37:20 +0200638 case LY_TYPE_BINARY:
639 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 case LY_TYPE_INT8:
641 case LY_TYPE_INT16:
642 case LY_TYPE_INT32:
643 case LY_TYPE_INT64:
644 case LY_TYPE_UINT8:
645 case LY_TYPE_UINT16:
646 case LY_TYPE_UINT32:
647 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200648 /* RFC 6020 9.2.4 - range */
649
650 /* length and range are actually the same restriction, so process
651 * them by this common code, we just need to differ the name and
652 * structure where the information will be stored
653 */
654 if (type->base == LY_TYPE_BINARY) {
655 restr = &type->info.binary.length;
656 name = "length";
657 } else {
658 restr = &type->info.num.range;
659 name = "range";
660 }
661
Radek Krejci73adb602015-07-02 18:07:40 +0200662 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200663 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
664 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200665 continue;
666 }
667
Radek Krejcif2860132015-06-20 12:37:20 +0200668 if (!strcmp(node->name, name)) {
669 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200670 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200671 goto error;
672 }
673
674 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200675 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200676 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200677 goto error;
678 }
679 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100680 if (!(*restr)) {
681 LOGMEM;
682 goto error;
683 }
Radek Krejcif2860132015-06-20 12:37:20 +0200684 (*restr)->expr = lydict_insert(module->ctx, value, 0);
685
686 /* get possible substatements */
687 if (read_restr_substmt(module->ctx, *restr, node)) {
688 goto error;
689 }
690 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200691 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200692 goto error;
693 }
Radek Krejcif2860132015-06-20 12:37:20 +0200694 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200695 break;
696
697 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200698 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200699 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200700 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
701 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200702 continue;
703 }
704
Michal Vasko88c29542015-11-27 14:57:53 +0100705 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200706 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200707 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200708 goto error;
709 }
710
711 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200712 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200713 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200714 if (!type->info.lref.path) {
715 goto error;
716 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200717 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200718 goto error;
719 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200720
Radek Krejcidc4c1412015-06-19 15:39:54 +0200721 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200722 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200723 goto error;
724 }
Radek Krejci73adb602015-07-02 18:07:40 +0200725 }
726
Michal Vasko88c29542015-11-27 14:57:53 +0100727 if (!type->info.lref.path && !type->der->type.der) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200728 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200729 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200730 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200731 break;
732
733 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200734 /* RFC 6020 9.4.4 - length */
735 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200736 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200737 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200738 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
739 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100740 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200741 continue;
742 }
743
Radek Krejci3733a802015-06-19 13:43:21 +0200744 if (!strcmp(node->name, "length")) {
745 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200746 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200747 goto error;
748 }
749
750 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200751 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200752 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200753 goto error;
754 }
755 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100756 if (!type->info.str.length) {
757 LOGMEM;
758 goto error;
759 }
Radek Krejci3733a802015-06-19 13:43:21 +0200760 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
761
Radek Krejci5fbc9162015-06-19 14:11:11 +0200762 /* get possible sub-statements */
763 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200764 goto error;
765 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100766 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200767 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200768 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200769 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200770 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200771 goto error;
772 }
773 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200774 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200775 if (i) {
776 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100777 if (!type->info.str.patterns) {
778 LOGMEM;
779 goto error;
780 }
Radek Krejci73adb602015-07-02 18:07:40 +0200781 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100782 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200783
784 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200785 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
786 if (!precomp) {
787 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200788 free(type->info.str.patterns);
789 goto error;
790 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200791 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200792
Radek Krejci73adb602015-07-02 18:07:40 +0200793 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200794
795 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100796 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200797 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200798 goto error;
799 }
Radek Krejci73adb602015-07-02 18:07:40 +0200800 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200801 }
802 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200803 break;
804
805 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200806 /* RFC 6020 7.4 - type */
807 /* count number of types in union */
808 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200809 LY_TREE_FOR_SAFE(yin->child, next, node) {
810 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
811 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100812 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200813 continue;
814 }
815
Radek Krejcie4c366b2015-07-02 10:11:31 +0200816 if (!strcmp(node->name, "type")) {
817 i++;
818 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200819 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200820 goto error;
821 }
822 }
823
824 if (!i) {
825 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100826 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200827 break;
828 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200829 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200830 goto error;
831 }
832
833 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200834 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100835 if (!type->info.uni.types) {
836 LOGMEM;
837 goto error;
838 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200839 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200840 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100841 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100842 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
843 if (!rc) {
844 type->info.uni.count++;
845
846 /* union's type cannot be empty or leafref */
847 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
848 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
849 rc = -1;
850 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
851 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
852 rc = -1;
853 }
854 }
855 if (rc) {
856 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
857 for (i = 0; i < type->info.uni.count; ++i) {
858 lys_type_free(module->ctx, &type->info.uni.types[i]);
859 }
860 free(type->info.uni.types);
861 type->info.uni.types = NULL;
862 type->info.uni.count = 0;
863
864 if (rc == EXIT_FAILURE) {
865 return EXIT_FAILURE;
866 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200867 goto error;
868 }
Michal Vasko88c29542015-11-27 14:57:53 +0100869 }
870 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200871
Michal Vasko88c29542015-11-27 14:57:53 +0100872 case LY_TYPE_BOOL:
873 case LY_TYPE_EMPTY:
874 /* no sub-statement allowed */
875 LY_TREE_FOR(yin->child, node) {
876 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
877 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200878 goto error;
879 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200880 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881 break;
882
883 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100884 LOGINT;
885 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 }
887
888 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200889
890error:
Michal Vasko88c29542015-11-27 14:57:53 +0100891 return -1;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200892}
893
Michal Vasko0d343d12015-08-24 14:57:36 +0200894/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200896fill_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 +0200897{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100899 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200900 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100903 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200904 goto error;
905 }
906 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +0200909 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200910 goto error;
911 }
Radek Krejcieac35532015-05-31 19:09:15 +0200912
Michal Vasko88c29542015-11-27 14:57:53 +0100913 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200914 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
915 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200916 continue;
917 }
918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100920 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200921 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 goto error;
923 }
Michal Vasko88c29542015-11-27 14:57:53 +0100924 /* HACK for unres */
925 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100926 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100927 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200928 goto error;
929 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200930 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200931 } else if (!strcmp(node->name, "default")) {
932 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200933 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200934 goto error;
935 }
936 GETVAL(value, node, "value");
937 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200938 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939 } else if (!strcmp(node->name, "units")) {
940 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200941 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 goto error;
943 }
944 GETVAL(value, node, "name");
945 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
946 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200947 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 goto error;
949 }
950 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200953 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200954 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200955 goto error;
956 }
Radek Krejcieac35532015-05-31 19:09:15 +0200957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200958 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200959 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +0200960 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200961 goto error;
962 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200966
967error:
968
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200969 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200970}
971
Michal Vasko0d343d12015-08-24 14:57:36 +0200972/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +0200973static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200974fill_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 +0200975{
976 const char *value;
977 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +0200978 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +0200979
Radek Krejcib05774c2015-06-18 13:52:59 +0200980 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100981 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +0200982 goto error;
983 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200984 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +0200985 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +0200986
Radek Krejci76512572015-08-04 09:47:08 +0200987 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +0200988 goto error;
989 }
990
991 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200992 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
993 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100994 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +0200995 continue;
996 }
997
Radek Krejci3cf9e222015-06-18 11:37:50 +0200998 if (!strcmp(child->name, "if-feature")) {
999 c++;
1000 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001001 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001002 goto error;
1003 }
1004 }
1005
1006 if (c) {
1007 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001008 if (!f->features) {
1009 LOGMEM;
1010 goto error;
1011 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001012 }
Radek Krejci73adb602015-07-02 18:07:40 +02001013 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001014 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001015 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001016 goto error;
1017 }
Radek Krejcicf509982015-12-15 09:22:44 +01001018 /* hack - store pointer to the parent node for later status check */
1019 f->features[f->features_size] = f;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001020 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001021 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001022 f->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001023 lydict_remove(module->ctx, value);
1024 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001025 goto error;
1026 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001027 }
1028
Radek Krejci3cf9e222015-06-18 11:37:50 +02001029 return EXIT_SUCCESS;
1030
1031error:
1032
1033 return EXIT_FAILURE;
1034}
1035
Michal Vasko0d343d12015-08-24 14:57:36 +02001036/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001037static int
Radek Krejcib8048692015-08-05 13:36:34 +02001038fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001039{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001043 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001044 if (!must->expr) {
1045 goto error;
1046 }
Radek Krejci800af702015-06-02 13:46:01 +02001047
Radek Krejci41726f92015-06-19 13:11:05 +02001048 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001049
Radek Krejci41726f92015-06-19 13:11:05 +02001050error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001052 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001053}
1054
Radek Krejci581ce772015-11-10 17:22:40 +01001055static int
Michal Vasko88c29542015-11-27 14:57:53 +01001056fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1057 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001058{
1059 int i, j;
1060 const char *value, *vaux;
1061
1062 /* get unique value (list of leafs supposed to be unique */
1063 GETVAL(value, yin, "tag");
1064
1065 /* count the number of unique leafs in the value */
1066 vaux = value;
1067 while ((vaux = strpbrk(vaux, " \t\n"))) {
1068 unique->expr_size++;
1069 while (isspace(*vaux)) {
1070 vaux++;
1071 }
1072 }
1073 unique->expr_size++;
1074 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001075 if (!unique->expr) {
1076 LOGMEM;
1077 goto error;
1078 }
Radek Krejci581ce772015-11-10 17:22:40 +01001079
1080 for (i = 0; i < unique->expr_size; i++) {
1081 vaux = strpbrk(value, " \t\n");
1082 if (!vaux) {
1083 /* the last token, lydict_insert() will count its size on its own */
1084 vaux = value;
1085 }
1086
1087 /* store token into unique structure */
1088 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1089
1090 /* check that the expression does not repeat */
1091 for (j = 0; j < i; j++) {
1092 if (unique->expr[j] == unique->expr[i]) {
1093 LOGVAL(LYE_INARG, LOGLINE(yin), unique->expr[i], "unique");
1094 LOGVAL(LYE_SPEC, 0, "The identifier is not unique");
1095 goto error;
1096 }
1097 }
1098
1099 /* try to resolve leaf */
1100 if (unres) {
1101 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1102 } else {
1103 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1104 goto error;
1105 }
1106 }
1107
1108 /* move to next token */
1109 value = vaux;
1110 while(isspace(*value)) {
1111 value++;
1112 }
1113 }
1114
1115 return EXIT_SUCCESS;
1116
1117error:
1118 return EXIT_FAILURE;
1119}
1120
Michal Vasko0d343d12015-08-24 14:57:36 +02001121/* logs directly
1122 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001123 * type: 0 - min, 1 - max
1124 */
1125static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001126deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001127{
1128 const char *value;
1129 char *endptr;
1130 unsigned long val;
1131 uint32_t *ui32val;
1132
1133 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001134 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001135 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001136 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001137 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001138 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001139 }
Radek Krejci76512572015-08-04 09:47:08 +02001140 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001141 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001142 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001143 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001144 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001145 }
1146 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001147 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1148 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001149 goto error;
1150 }
1151
1152 GETVAL(value, node, "value");
1153 while (isspace(value[0])) {
1154 value++;
1155 }
1156
1157 /* convert it to uint32_t */
1158 errno = 0;
1159 endptr = NULL;
1160 val = strtoul(value, &endptr, 10);
1161 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001162 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001163 goto error;
1164 }
1165 if (type) {
1166 d->max = (uint32_t)val;
1167 } else {
1168 d->min = (uint32_t)val;
1169 }
1170
1171 if (d->mod == LY_DEVIATE_ADD) {
1172 /* check that there is no current value */
1173 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001174 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1175 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001176 goto error;
1177 }
1178 }
1179
1180 if (d->mod == LY_DEVIATE_DEL) {
1181 /* check values */
1182 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001183 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1184 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001185 goto error;
1186 }
1187 /* remove current min-elements value of the target */
1188 *ui32val = 0;
1189 } else { /* add (already checked) and replace */
1190 /* set new value specified in deviation */
1191 *ui32val = (uint32_t)val;
1192 }
1193
1194 return EXIT_SUCCESS;
1195
1196error:
1197
1198 return EXIT_FAILURE;
1199}
1200
Michal Vasko0d343d12015-08-24 14:57:36 +02001201/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001202static int
Michal Vasko88c29542015-11-27 14:57:53 +01001203fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1204 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001205{
1206 const char *value, **stritem;
1207 struct lyxml_elem *next, *child, *develem;
1208 int c_dev = 0, c_must, c_uniq;
1209 int f_min = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001210 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001211 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001212 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001213 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001214 struct lys_node_choice *choice = NULL;
1215 struct lys_node_leaf *leaf = NULL;
1216 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001217 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001218 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001219 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001220
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001221 ctx = module->ctx;
1222
Radek Krejcieb00f512015-07-01 16:44:58 +02001223 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001224 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001225 if (!dev->target_name) {
1226 goto error;
1227 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001228
1229 /* resolve target node */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001230 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev->target);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001231 if (rc || !dev->target) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001232 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001233 goto error;
1234 }
1235 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001236 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001237 goto error;
1238 }
1239 /* mark the target module as deviated */
1240 dev->target->module->deviated = 1;
1241
1242 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001243 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1244 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001245 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001246 continue;
1247 }
1248
Radek Krejcieb00f512015-07-01 16:44:58 +02001249 if (!strcmp(child->name, "description")) {
1250 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001251 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001252 goto error;
1253 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001254 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001255 if (!dev->dsc) {
1256 goto error;
1257 }
1258 } else if (!strcmp(child->name, "reference")) {
1259 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001260 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001261 goto error;
1262 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001263 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001264 if (!dev->ref) {
1265 goto error;
1266 }
1267 } else if (!strcmp(child->name, "deviate")) {
1268 c_dev++;
1269
Michal Vasko345da0a2015-12-02 10:35:55 +01001270 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001271 * further processed later
1272 */
1273 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001274
Radek Krejcieb00f512015-07-01 16:44:58 +02001275 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001276 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001277 goto error;
1278 }
1279
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001280 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001281 }
1282
1283 if (c_dev) {
1284 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001285 if (!dev->deviate) {
1286 LOGMEM;
1287 goto error;
1288 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001289 }
1290
1291 LY_TREE_FOR(yin->child, develem) {
1292 /* init */
1293 f_min = 0;
1294 c_must = 0;
1295 c_uniq = 0;
1296
1297 /* get deviation type */
1298 GETVAL(value, develem, "value");
1299 if (!strcmp(value, "not-supported")) {
1300 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1301 /* no property expected in this case */
1302 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001303 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001304 goto error;
1305 }
1306
Radek Krejci5b917642015-07-02 09:03:13 +02001307 /* and neither any other deviate statement is expected,
1308 * not-supported deviation must be the only deviation of the target
1309 */
1310 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001311 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1312 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001313 goto error;
1314 }
1315
1316
Radek Krejcieb00f512015-07-01 16:44:58 +02001317 /* remove target node */
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001318 lys_node_free(dev->target, NULL);
Radek Krejci5b917642015-07-02 09:03:13 +02001319 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001320
Radek Krejci5b917642015-07-02 09:03:13 +02001321 dev->deviate_size = 1;
1322 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001323 } else if (!strcmp(value, "add")) {
1324 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1325 } else if (!strcmp(value, "replace")) {
1326 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1327 } else if (!strcmp(value, "delete")) {
1328 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1329 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001330 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001331 goto error;
1332 }
1333 d = &dev->deviate[dev->deviate_size];
1334
1335 /* process deviation properties */
1336 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001337 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1338 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001339 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001340 continue;
1341 }
1342
Radek Krejcieb00f512015-07-01 16:44:58 +02001343 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001344 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001345 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001346 goto error;
1347 }
1348
1349 /* for we deviate from RFC 6020 and allow config property even it is/is not
1350 * specified in the target explicitly since config property inherits. So we expect
1351 * that config is specified in every node. But for delete, we check that the value
1352 * is the same as here in deviation
1353 */
1354 GETVAL(value, child, "value");
1355 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001356 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001357 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001358 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001359 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001360 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001361 goto error;
1362 }
1363
1364 if (d->mod == LY_DEVIATE_DEL) {
1365 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001366 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001367 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1368 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001369 goto error;
1370 }
1371 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001372 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001373
1374 /* ... and inherit config value from the target's parent */
1375 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001376 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001377 } else {
1378 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001379 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001380 }
1381 } else { /* add and replace are the same in this case */
1382 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001383 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001384
1385 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001386 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001387 }
1388 } else if (!strcmp(child->name, "default")) {
1389 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001390 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001391 goto error;
1392 }
1393 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001394 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001395
Radek Krejci76512572015-08-04 09:47:08 +02001396 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001397 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001398
1399 if (d->mod == LY_DEVIATE_ADD) {
1400 /* check that there is no current value */
1401 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001402 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1403 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001404 goto error;
1405 }
1406 }
1407
Michal Vasko3edeaf72016-02-11 13:17:43 +01001408 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001409 if (rc || !node) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001410 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1411 goto error;
1412 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001413 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001414 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001415 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1416 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001417 goto error;
1418 }
1419 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001420 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001421 if (!choice->dflt) {
1422 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001423 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001424 goto error;
1425 }
1426 }
Radek Krejci76512572015-08-04 09:47:08 +02001427 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001428 leaf = (struct lys_node_leaf *)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 (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001433 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1434 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 goto error;
1436 }
1437 }
1438
1439 if (d->mod == LY_DEVIATE_DEL) {
1440 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001441 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1442 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001443 goto error;
1444 }
1445 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001446 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001447 leaf->dflt = NULL;
1448 } else { /* add (already checked) and replace */
1449 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001450 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001451
1452 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001453 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 }
1455 } else {
1456 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001457 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1458 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001459 goto error;
1460 }
1461 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001462 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001463 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001464 goto error;
1465 }
1466
1467 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001468 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001469 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1470 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 goto error;
1472 }
1473
1474 GETVAL(value, child, "value");
1475 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001476 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001477 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001478 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001479 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001480 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001481 goto error;
1482 }
1483
1484 if (d->mod == LY_DEVIATE_ADD) {
1485 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001486 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001487 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1488 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001489 goto error;
1490 }
1491 }
1492
1493 if (d->mod == LY_DEVIATE_DEL) {
1494 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001495 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001496 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1497 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001498 goto error;
1499 }
1500 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001501 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 } else { /* add (already checked) and replace */
1503 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001504 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001505
1506 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001507 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001508 }
1509 } else if (!strcmp(child->name, "min-elements")) {
1510 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001511 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 goto error;
1513 }
1514 f_min = 1;
1515
1516 if (deviate_minmax(dev->target, child, d, 0)) {
1517 goto error;
1518 }
1519 } else if (!strcmp(child->name, "max-elements")) {
1520 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001521 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001522 goto error;
1523 }
1524
1525 if (deviate_minmax(dev->target, child, d, 1)) {
1526 goto error;
1527 }
1528 } else if (!strcmp(child->name, "must")) {
1529 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001530 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001531 continue;
1532 } else if (!strcmp(child->name, "type")) {
1533 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001534 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001535 goto error;
1536 }
1537
1538 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001539 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001540 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001541 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001542 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001544 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1545 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001546 goto error;
1547 }
1548
1549 if (d->mod == LY_DEVIATE_ADD) {
1550 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001551 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1552 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001553 goto error;
1554 } else if (d->mod == LY_DEVIATE_DEL) {
1555 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001556 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1557 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001558 goto error;
1559 }
1560
1561 /* replace */
1562 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001563 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001564
1565 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001566 /* HACK for unres */
1567 t->der = (struct lys_tpdf *)child;
1568 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev->target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001569 goto error;
1570 }
1571 d->type = t;
1572 } else if (!strcmp(child->name, "unique")) {
1573 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001574 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001575 continue;
1576 } else if (!strcmp(child->name, "units")) {
1577 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001578 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001579 goto error;
1580 }
1581
1582 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001583 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001584 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001585 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001586 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001588 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1589 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001590 goto error;
1591 }
1592
1593 /* get units value */
1594 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001595 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001596
1597 /* apply to target */
1598 if (d->mod == LY_DEVIATE_ADD) {
1599 /* check that there is no current value */
1600 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001601 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1602 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001603 goto error;
1604 }
1605 }
1606
1607 if (d->mod == LY_DEVIATE_DEL) {
1608 /* check values */
1609 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001610 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1611 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001612 goto error;
1613 }
1614 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001615 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001616 } else { /* add (already checked) and replace */
1617 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001618 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001619
1620 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001621 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 }
1623 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001624 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001625 goto error;
1626 }
1627
Michal Vasko88c29542015-11-27 14:57:53 +01001628 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001629 }
1630
1631 if (c_must) {
1632 /* check target node type */
1633 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001634 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001635 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1636 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 break;
Radek Krejci76512572015-08-04 09:47:08 +02001638 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001639 trg_must = &((struct lys_node_container *)dev->target)->must;
1640 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 break;
Radek Krejci76512572015-08-04 09:47:08 +02001642 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001643 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1644 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 break;
Radek Krejci76512572015-08-04 09:47:08 +02001646 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001647 trg_must = &((struct lys_node_list *)dev->target)->must;
1648 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001649 break;
Radek Krejci76512572015-08-04 09:47:08 +02001650 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001651 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1652 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 break;
1654 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001655 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1656 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001657 goto error;
1658 }
1659
1660 if (d->mod == LY_DEVIATE_RPL) {
1661 /* remove target's musts and allocate new array for it */
1662 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001663 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1664 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 goto error;
1666 }
1667
1668 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001669 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001670 }
1671 free(*trg_must);
1672 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1673 d->must_size = c_must;
1674 *trg_must_size = 0;
1675 } else if (d->mod == LY_DEVIATE_ADD) {
1676 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001677 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001678 if (!d->must) {
1679 LOGMEM;
1680 goto error;
1681 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001683 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001684 d->must_size = c_must;
1685 } else { /* LY_DEVIATE_DEL */
1686 d->must = calloc(c_must, sizeof *d->must);
1687 }
Michal Vasko253035f2015-12-17 16:58:13 +01001688 if (!d->must) {
1689 LOGMEM;
1690 goto error;
1691 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 }
1693 if (c_uniq) {
1694 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001695 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001696 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1697 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001698 goto error;
1699 }
1700
Radek Krejcib8048692015-08-05 13:36:34 +02001701 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001702 if (d->mod == LY_DEVIATE_RPL) {
1703 /* remove target's unique and allocate new array for it */
1704 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001705 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1706 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001707 goto error;
1708 }
1709
1710 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001711 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001712 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001713 }
1714 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001715 }
1716 free(list->unique);
1717 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1718 d->unique_size = c_uniq;
1719 list->unique_size = 0;
1720 } else if (d->mod == LY_DEVIATE_ADD) {
1721 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001722 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001723 list->unique = d->unique;
1724 d->unique = &list->unique[list->unique_size];
1725 d->unique_size = c_uniq;
1726 } else { /* LY_DEVIATE_DEL */
1727 d->unique = calloc(c_uniq, sizeof *d->unique);
1728 }
Michal Vasko253035f2015-12-17 16:58:13 +01001729 if (!d->unique) {
1730 LOGMEM;
1731 goto error;
1732 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001733 }
1734
1735 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001736 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001737 if (!strcmp(child->name, "must")) {
1738 if (d->mod == LY_DEVIATE_DEL) {
1739 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1740 goto error;
1741 }
1742
1743 /* find must to delete, we are ok with just matching conditions */
1744 for (i = 0; i < *trg_must_size; i++) {
1745 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1746 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001747 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001748 /* ... and maintain the array */
1749 (*trg_must_size)--;
1750 if (i != *trg_must_size) {
1751 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1752 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1753 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1754 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1755 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1756 }
1757 if (!(*trg_must_size)) {
1758 free(*trg_must);
1759 *trg_must = NULL;
1760 } else {
1761 (*trg_must)[*trg_must_size].expr = NULL;
1762 (*trg_must)[*trg_must_size].dsc = NULL;
1763 (*trg_must)[*trg_must_size].ref = NULL;
1764 (*trg_must)[*trg_must_size].eapptag = NULL;
1765 (*trg_must)[*trg_must_size].emsg = NULL;
1766 }
1767
1768 i = -1; /* set match flag */
1769 break;
1770 }
1771 }
1772 d->must_size++;
1773 if (i != -1) {
1774 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001775 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1776 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001777 goto error;
1778 }
1779 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001780 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1781 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001782 goto error;
1783 }
1784 (*trg_must_size)++;
1785 }
1786 } else if (!strcmp(child->name, "unique")) {
1787 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci581ce772015-11-10 17:22:40 +01001788 if (fill_yin_unique(module, dev->target, child, &d->unique[d->unique_size], NULL)) {
1789 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 goto error;
1791 }
1792
1793 /* find unique structures to delete */
1794 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001795 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001796 continue;
1797 }
1798
Radek Krejci581ce772015-11-10 17:22:40 +01001799 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1800 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 break;
1802 }
1803 }
1804
Radek Krejci581ce772015-11-10 17:22:40 +01001805 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001806 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001807 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001808 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001809 }
1810 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 /* ... and maintain the array */
1812 list->unique_size--;
1813 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001814 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1815 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 }
1817
1818 if (!list->unique_size) {
1819 free(list->unique);
1820 list->unique = NULL;
1821 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001822 list->unique[list->unique_size].expr_size = 0;
1823 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 }
1825
1826 i = -1; /* set match flag */
1827 break;
1828 }
1829 }
1830
1831 d->unique_size++;
1832 if (i != -1) {
1833 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001834 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1835 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001836 goto error;
1837 }
1838 } else { /* replace or add */
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001839 i = fill_yin_unique(module, dev->target, child, &list->unique[list->unique_size], NULL);
1840 list->unique_size++;
1841 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001842 goto error;
1843 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 }
1845 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001846 }
Radek Krejci5b917642015-07-02 09:03:13 +02001847
1848 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001849 }
1850
Radek Krejcieb00f512015-07-01 16:44:58 +02001851 return EXIT_SUCCESS;
1852
1853error:
1854
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 return EXIT_FAILURE;
1856}
1857
Michal Vasko0d343d12015-08-24 14:57:36 +02001858/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001859static int
Radek Krejcib8048692015-08-05 13:36:34 +02001860fill_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 +02001861 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001862{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001864 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001865 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001866 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001867
Michal Vasko591e0b22015-08-13 13:53:43 +02001868 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001869 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001870 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001871 if (!aug->target_name) {
1872 goto error;
1873 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001875
Michal Vasko1d87a922015-08-21 12:57:16 +02001876 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001877 goto error;
1878 }
1879
1880 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001881 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1882 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001883 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001884 continue;
1885 }
1886
Radek Krejci3cf9e222015-06-18 11:37:50 +02001887 if (!strcmp(child->name, "if-feature")) {
1888 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001889 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001890 } else if (!strcmp(child->name, "when")) {
1891 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001892 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001893 goto error;
1894 }
1895
1896 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001897 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001898 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001899 goto error;
1900 }
Michal Vaskofcdac172015-10-07 09:35:05 +02001901 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001902 goto error;
1903 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001904 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001905 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001906
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001907 /* check allowed data sub-statements */
1908 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001909 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001910 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001911 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001912 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001913 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001914 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001916 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001917 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001918 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001919 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001920 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001921 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001923 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001924 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001925 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001926 goto error;
1927 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001928
Radek Krejci1d82ef62015-08-07 14:44:40 +02001929 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001930 goto error;
1931 }
1932
1933 /* check for mandatory nodes - if the target node is in another module
1934 * the added nodes cannot be mandatory
1935 */
Radek Krejcic6556022016-01-27 15:16:45 +01001936 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001937 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001938 goto error;
1939 }
1940
Radek Krejci1d82ef62015-08-07 14:44:40 +02001941 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001942 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001943 }
1944
1945 if (c) {
1946 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001947 if (!aug->features) {
1948 LOGMEM;
1949 goto error;
1950 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001951 }
1952
1953 LY_TREE_FOR_SAFE(yin->child, next, child) {
1954 if (!strcmp(child->name, "if-feature")) {
1955 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001956 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001957 goto error;
1958 }
Radek Krejcicf509982015-12-15 09:22:44 +01001959 /* hack - store pointer to the parent node for later status check */
1960 aug->features[aug->features_size] = (struct lys_feature *)aug;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001961 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001962 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001963 aug->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001964 lydict_remove(module->ctx, value);
1965 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001966 goto error;
1967 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001968 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001969 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001970 }
1971
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001972 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02001973 * connected to the tree and adjusted (if possible right now).
1974 * However, if this is augment in a uses, it gets resolved
1975 * when the uses does and cannot be resolved now for sure
1976 * (the grouping was not yet copied into uses).
1977 */
1978 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001979 if (resolve_augment(aug, NULL)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02001980 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
1981 goto error;
1982 }
Michal Vasko49291b32015-08-06 09:49:41 +02001983 }
Radek Krejci106efc02015-06-10 14:36:27 +02001984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001985 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02001986
1987error:
1988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02001990}
1991
Michal Vasko0d343d12015-08-24 14:57:36 +02001992/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001993static int
Michal Vasko0d204592015-10-07 09:50:04 +02001994fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02001995{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 struct lyxml_elem *sub, *next;
1997 const char *value;
1998 char *endptr;
1999 int f_mand = 0, f_min = 0, f_max = 0;
2000 int c_must = 0;
2001 int r;
2002 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002003
Radek Krejci76512572015-08-04 09:47:08 +02002004 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 goto error;
2006 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002007
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002009 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002010 if (!rfn->target_name) {
2011 goto error;
2012 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002013
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002015 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2016 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002017 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002018 continue;
2019 }
2020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 /* limited applicability */
2022 if (!strcmp(sub->name, "default")) {
2023 /* leaf or choice */
2024 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002025 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 goto error;
2027 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 /* check possibility of statements combination */
2030 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002031 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002032 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002033 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 goto error;
2035 }
2036 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002037 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002040 GETVAL(value, sub, "value");
2041 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2042 } else if (!strcmp(sub->name, "mandatory")) {
2043 /* leaf, choice or anyxml */
2044 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002045 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 goto error;
2047 }
2048 /* just checking the flags in leaf is not sufficient, we would allow
2049 * multiple mandatory statements with the "false" value
2050 */
2051 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002053 /* check possibility of statements combination */
2054 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002055 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002057 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 goto error;
2059 }
2060 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002061 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 GETVAL(value, sub, "value");
2065 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002066 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002068 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002070 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 goto error;
2072 }
2073 } else if (!strcmp(sub->name, "min-elements")) {
2074 /* list or leaf-list */
2075 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002076 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 goto error;
2078 }
2079 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 /* check possibility of statements combination */
2082 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002083 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002085 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 goto error;
2087 }
2088 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002089 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 GETVAL(value, sub, "value");
2093 while (isspace(value[0])) {
2094 value++;
2095 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 /* convert it to uint32_t */
2098 errno = 0;
2099 endptr = NULL;
2100 val = strtoul(value, &endptr, 10);
2101 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002102 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 goto error;
2104 }
2105 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 /* magic - bit 3 in flags means min set */
2108 rfn->flags |= 0x04;
2109 } else if (!strcmp(sub->name, "max-elements")) {
2110 /* list or leaf-list */
2111 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002112 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 goto error;
2114 }
2115 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 /* check possibility of statements combination */
2118 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002119 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002121 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 goto error;
2123 }
2124 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002125 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 GETVAL(value, sub, "value");
2129 while (isspace(value[0])) {
2130 value++;
2131 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 /* convert it to uint32_t */
2134 errno = 0;
2135 endptr = NULL;
2136 val = strtoul(value, &endptr, 10);
2137 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002138 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 goto error;
2140 }
2141 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 /* magic - bit 4 in flags means min set */
2144 rfn->flags |= 0x08;
2145 } else if (!strcmp(sub->name, "presence")) {
2146 /* container */
2147 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002148 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 goto error;
2150 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 /* check possibility of statements combination */
2153 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002154 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002156 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 goto error;
2158 }
2159 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002160 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 GETVAL(value, sub, "value");
2164 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2165 } else if (!strcmp(sub->name, "must")) {
2166 /* leaf-list, list, container or anyxml */
2167 /* check possibility of statements combination */
2168 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002169 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002171 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 goto error;
2173 }
2174 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002175 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002179 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002182 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 goto error;
2184 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002185
Michal Vasko345da0a2015-12-02 10:35:55 +01002186 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 /* process nodes with cardinality of 0..n */
2190 if (c_must) {
2191 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002192 if (!rfn->must) {
2193 LOGMEM;
2194 goto error;
2195 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 }
Radek Krejci73adb602015-07-02 18:07:40 +02002197 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002198 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2199 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002200 if (r) {
2201 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 }
Michal Vasko0d204592015-10-07 09:50:04 +02002203 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002204 goto error;
2205 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002209
2210error:
2211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002213}
2214
Michal Vasko0d343d12015-08-24 14:57:36 +02002215/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216static int
Radek Krejcib8048692015-08-05 13:36:34 +02002217fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002218{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 struct lyxml_elem *child;
2220 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002221 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002224 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2225 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002226 continue;
2227 }
2228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 if (!strcmp(child->name, "prefix")) {
2230 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002231 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 goto error;
2233 }
2234 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2235 } else if (!strcmp(child->name, "revision-date")) {
2236 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002237 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 goto error;
2239 }
2240 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002241 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 goto error;
2243 }
2244 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2245 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002246 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 goto error;
2248 }
2249 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 /* check mandatory information */
2252 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002253 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 goto error;
2255 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002258
2259 /* check for circular import, store it if passed */
2260 if (!module->ctx->models.parsing) {
2261 count = 0;
2262 } else {
2263 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2264 if (value == module->ctx->models.parsing[count]) {
2265 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2266 goto error;
2267 }
2268 }
2269 }
2270 ++count;
2271 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002272 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2273 if (!module->ctx->models.parsing) {
2274 LOGMEM;
2275 goto error;
2276 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002277 module->ctx->models.parsing[count - 1] = value;
2278 module->ctx->models.parsing[count] = NULL;
2279
2280 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002281 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 +02002282 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002283 /* whether to use a user callback is decided in the function */
2284 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 +02002285 }
2286
2287 /* remove the new module name now that its parsing is finished (even if failed) */
2288 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2289 LOGINT;
2290 }
2291 --count;
2292 if (count) {
2293 module->ctx->models.parsing[count] = NULL;
2294 } else {
2295 free(module->ctx->models.parsing);
2296 module->ctx->models.parsing = NULL;
2297 }
2298
2299 /* check the result */
2300 if (!imp->module) {
2301 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2302 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2303 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002307
2308error:
2309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002311}
2312
Michal Vasko0d343d12015-08-24 14:57:36 +02002313/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002315fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2316 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002317{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 struct lyxml_elem *child;
2319 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002320 char *module_data;
2321 void (*module_data_free)(char *module_data) = NULL;
2322 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002323 int count, i;
Radek Krejciefaeba32015-05-27 14:30:57 +02002324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002326 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2327 /* garbage */
2328 continue;
2329 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 if (!strcmp(child->name, "revision-date")) {
2331 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002332 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002333 goto error;
2334 }
2335 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002336 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 goto error;
2338 }
2339 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2340 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002341 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 goto error;
2343 }
2344 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002347
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002348 /* check that the submodule was not included yet (previous submodule could have included it) */
2349 for (i = 0; i < module->inc_size; ++i) {
2350 if (module->inc[i].submodule && (module->inc[i].submodule->name == value)) {
Michal Vasko5ff78822016-02-12 09:33:31 +01002351 /* copy the duplicate into the result */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002352 memcpy(inc, &module->inc[i], sizeof *inc);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002353
Michal Vasko5ff78822016-02-12 09:33:31 +01002354 if (submodule) {
2355 /* we don't care if it was external or not */
2356 inc->external = 0;
2357 } else if (inc->external) {
2358 /* remove the duplicate */
2359 --module->inc_size;
2360 memmove(&module->inc[i], &module->inc[i + 1], (module->inc_size - i) * sizeof *inc);
2361 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
2362
2363 /* it is no longer external */
2364 inc->external = 0;
2365 }
2366 /* if !submodule && !inc->external, we just create a duplicate so it is detected and ended with error */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002367
2368 return EXIT_SUCCESS;
2369 }
2370 }
2371
Michal Vasko1b882eb2015-10-22 11:43:14 +02002372 /* check for circular include, store it if passed */
2373 if (!module->ctx->models.parsing) {
2374 count = 0;
2375 } else {
2376 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2377 if (value == module->ctx->models.parsing[count]) {
2378 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2379 goto error;
2380 }
2381 }
2382 }
2383 ++count;
2384 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002385 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2386 if (!module->ctx->models.parsing) {
2387 LOGMEM;
2388 goto error;
2389 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002390 module->ctx->models.parsing[count - 1] = value;
2391 module->ctx->models.parsing[count] = NULL;
2392
2393 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002394 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002396 if (module->ctx->module_clb) {
2397 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2398 &format, &module_data_free);
2399 if (module_data) {
Radek Krejcic071c542016-01-27 14:57:51 +01002400 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002401 if (module_data_free) {
2402 module_data_free(module_data);
2403 } else {
2404 free(module_data);
2405 }
2406 } else {
2407 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2408 }
2409 } else {
2410 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
Radek Krejcic071c542016-01-27 14:57:51 +01002411 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002412 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002413 }
2414
2415 /* remove the new submodule name now that its parsing is finished (even if failed) */
2416 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2417 LOGINT;
2418 }
2419 --count;
2420 if (count) {
2421 module->ctx->models.parsing[count] = NULL;
2422 } else {
2423 free(module->ctx->models.parsing);
2424 module->ctx->models.parsing = NULL;
2425 }
2426
2427 /* check the result */
2428 if (!inc->submodule) {
2429 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2430 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2431 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002433
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002434 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002435
2436error:
2437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002439}
2440
Michal Vasko0d343d12015-08-24 14:57:36 +02002441/* logs directly
2442 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002443 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002444 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002445 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002446 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002447static int
Radek Krejcib8048692015-08-05 13:36:34 +02002448read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002449 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002450{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002451 const char *value;
2452 struct lyxml_elem *sub, *next;
2453 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002456 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002457 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 if (opt & OPT_IDENT) {
2460 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002461 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 goto error;
2463 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002464 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002466
Radek Krejci6764bb32015-07-03 15:16:04 +02002467 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002468 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002469 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002470 }
2471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002472 /* process local parameters */
2473 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002474 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002475 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002476 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002477 continue;
2478 }
2479 if (strcmp(sub->ns->value, LY_NSYIN)) {
2480 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002481 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002482 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002483 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002484 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002486 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002487 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002488 goto error;
2489 }
2490 }
2491
2492 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002493 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002494 continue;
2495 }
2496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002497 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002498 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002499 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 goto error;
2501 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002502 node->dsc = read_yin_subnode(ctx, sub, "text");
2503 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002504 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 }
2506 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002507 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002508 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 goto error;
2510 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002511 node->ref = read_yin_subnode(ctx, sub, "text");
2512 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002513 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002514 }
2515 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002516 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002517 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002518 goto error;
2519 }
2520 GETVAL(value, sub, "value");
2521 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002522 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002523 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002524 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002526 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002528 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002529 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530 }
2531 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002532 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002533 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 goto error;
2535 }
2536 GETVAL(value, sub, "value");
2537 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002538 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002540 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002542 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002543 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002544 }
2545 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002546 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002547 continue;
2548 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002549 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002551
Radek Krejci1d82ef62015-08-07 14:44:40 +02002552 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 /* get config flag from parent */
2554 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002555 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 } else {
2557 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002558 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002559 }
2560 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002562 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002563
2564error:
2565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002566 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002567}
2568
Michal Vasko0d343d12015-08-24 14:57:36 +02002569/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002570static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002571read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002572{
Radek Krejci76512572015-08-04 09:47:08 +02002573 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002574 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002575 const char *value;
2576
2577 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002578 if (!retval) {
2579 LOGMEM;
2580 return NULL;
2581 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002582
2583 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002584 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002585 if (!retval->cond) {
2586 goto error;
2587 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002588
Radek Krejci73adb602015-07-02 18:07:40 +02002589 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002590 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2591 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002592 continue;
2593 }
2594
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002595 if (!strcmp(child->name, "description")) {
2596 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002597 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002598 goto error;
2599 }
2600 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2601 if (!retval->dsc) {
2602 goto error;
2603 }
2604 } else if (!strcmp(child->name, "reference")) {
2605 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002606 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002607 goto error;
2608 }
2609 retval->ref = read_yin_subnode(module->ctx, child, "text");
2610 if (!retval->ref) {
2611 goto error;
2612 }
2613 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002614 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002615 goto error;
2616 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002617 }
2618
2619 return retval;
2620
2621error:
2622
Michal Vasko0308dd62015-10-07 09:14:40 +02002623 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002624 return NULL;
2625}
2626
Michal Vasko0d343d12015-08-24 14:57:36 +02002627/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002628static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002629read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2630 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002631{
Michal Vasko29fc0182015-08-24 15:02:39 +02002632 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002633 struct lys_node_case *cs;
2634 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002635 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002636 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002637
Radek Krejcie867c852015-08-27 09:52:34 +02002638 /* init */
2639 memset(&root, 0, sizeof root);
2640
Radek Krejci1d82ef62015-08-07 14:44:40 +02002641 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002642 if (!cs) {
2643 LOGMEM;
2644 return NULL;
2645 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002646 cs->nodetype = LYS_CASE;
2647 cs->prev = (struct lys_node *)cs;
2648 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002649
Radek Krejci6a113852015-07-03 16:04:20 +02002650 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 goto error;
2652 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002653
Radek Krejcia9544502015-08-14 08:24:29 +02002654 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2655
Michal Vasko3a0043f2015-08-12 12:11:30 +02002656 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002657 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002658 goto error;
2659 }
2660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002661 /* process choice's specific children */
2662 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002663 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2664 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002665 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002666 continue;
2667 }
2668
Michal Vasko29fc0182015-08-24 15:02:39 +02002669 if (!strcmp(sub->name, "container") ||
2670 !strcmp(sub->name, "leaf-list") ||
2671 !strcmp(sub->name, "leaf") ||
2672 !strcmp(sub->name, "list") ||
2673 !strcmp(sub->name, "uses") ||
2674 !strcmp(sub->name, "choice") ||
2675 !strcmp(sub->name, "anyxml")) {
2676
Michal Vaskof3930de2015-10-22 12:03:59 +02002677 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002678 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002679 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002680 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002681 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002682 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002683 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002684 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002685 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002686 goto error;
2687 }
2688
Radek Krejci1d82ef62015-08-07 14:44:40 +02002689 cs->when = read_yin_when(module, sub);
2690 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002691 goto error;
2692 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002693 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002694 goto error;
2695 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002696
Michal Vasko345da0a2015-12-02 10:35:55 +01002697 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002698 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002699 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002703
Radek Krejci3cf9e222015-06-18 11:37:50 +02002704 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002705 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002706 if (!cs->features) {
2707 LOGMEM;
2708 goto error;
2709 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002710 }
Radek Krejci73adb602015-07-02 18:07:40 +02002711 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002712 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002713 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002714 goto error;
2715 }
Radek Krejcicf509982015-12-15 09:22:44 +01002716 /* hack - store pointer to the parent node for later status check */
2717 cs->features[cs->features_size] = (struct lys_feature *)cs;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002718 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002719 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002720 cs->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002721 lydict_remove(module->ctx, value);
2722 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002723 goto error;
2724 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 }
Radek Krejcib388c152015-06-04 17:03:03 +02002726
Michal Vasko29fc0182015-08-24 15:02:39 +02002727 /* last part - process data nodes */
2728 LY_TREE_FOR_SAFE(root.child, next, sub) {
2729 if (!strcmp(sub->name, "container")) {
2730 node = read_yin_container(module, retval, sub, resolve, unres);
2731 } else if (!strcmp(sub->name, "leaf-list")) {
2732 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2733 } else if (!strcmp(sub->name, "leaf")) {
2734 node = read_yin_leaf(module, retval, sub, resolve, unres);
2735 } else if (!strcmp(sub->name, "list")) {
2736 node = read_yin_list(module, retval, sub, resolve, unres);
2737 } else if (!strcmp(sub->name, "choice")) {
2738 node = read_yin_choice(module, retval, sub, resolve, unres);
2739 } else if (!strcmp(sub->name, "uses")) {
2740 node = read_yin_uses(module, retval, sub, resolve, unres);
2741 } else if (!strcmp(sub->name, "anyxml")) {
2742 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2743 }
2744 if (!node) {
2745 goto error;
2746 }
2747
Michal Vasko345da0a2015-12-02 10:35:55 +01002748 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002749 }
2750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002751 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002752
2753error:
2754
Michal Vasko29fc0182015-08-24 15:02:39 +02002755 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002756 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002757 }
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002758 lys_node_free(retval, NULL);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002760 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002761}
2762
Michal Vasko0d343d12015-08-24 14:57:36 +02002763/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002764static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002765read_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 +02002766{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002767 struct lyxml_elem *sub, *next;
2768 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002769 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002770 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002771 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002772 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002775 if (!choice) {
2776 LOGMEM;
2777 return NULL;
2778 }
Radek Krejci76512572015-08-04 09:47:08 +02002779 choice->nodetype = LYS_CHOICE;
2780 choice->prev = (struct lys_node *)choice;
2781 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002782
Michal Vaskoe0c59842015-09-24 13:52:20 +02002783 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2784 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 goto error;
2786 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002787
Radek Krejcia9544502015-08-14 08:24:29 +02002788 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2789
Michal Vasko3a0043f2015-08-12 12:11:30 +02002790 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002791 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002792 goto error;
2793 }
2794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002795 /* process choice's specific children */
2796 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002797 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2798 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002799 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002800 continue;
2801 }
2802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002804 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002805 goto error;
2806 }
2807 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002808 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 goto error;
2810 }
2811 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002812 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002813 goto error;
2814 }
2815 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002816 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002817 goto error;
2818 }
2819 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002820 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 goto error;
2822 }
2823 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002824 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 goto error;
2826 }
2827 } else if (!strcmp(sub->name, "default")) {
2828 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002829 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 goto error;
2831 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002832 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 } else if (!strcmp(sub->name, "mandatory")) {
2834 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002835 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 goto error;
2837 }
2838 /* just checking the flags in leaf is not sufficient, we would allow
2839 * multiple mandatory statements with the "false" value
2840 */
2841 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002843 GETVAL(value, sub, "value");
2844 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002845 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002846 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002847 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002848 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002849 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 goto error;
2851 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002852 } else if (!strcmp(sub->name, "when")) {
2853 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002854 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002855 goto error;
2856 }
2857
2858 choice->when = read_yin_when(module, sub);
2859 if (!choice->when) {
2860 goto error;
2861 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002862 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002863 goto error;
2864 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002865 } else if (!strcmp(sub->name, "if-feature")) {
2866 c_ftrs++;
2867
Michal Vasko345da0a2015-12-02 10:35:55 +01002868 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002869 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002870 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002871 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002872 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002873 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002874
Radek Krejci1d82ef62015-08-07 14:44:40 +02002875 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002876 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002878
Radek Krejci3cf9e222015-06-18 11:37:50 +02002879 if (c_ftrs) {
2880 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002881 if (!choice->features) {
2882 LOGMEM;
2883 goto error;
2884 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002885 }
2886
Radek Krejci73adb602015-07-02 18:07:40 +02002887 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002888 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002889 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002890 goto error;
2891 }
Radek Krejcicf509982015-12-15 09:22:44 +01002892 /* hack - store pointer to the parent node for later status check */
2893 choice->features[choice->features_size] = (struct lys_feature *)choice;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002894 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002895 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002896 choice->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002897 lydict_remove(module->ctx, value);
2898 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002899 goto error;
2900 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002901 }
2902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002903 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002904 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002905 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2907 goto error;
2908 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 /* link default with the case */
2911 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002912 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002913 goto error;
2914 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002918
2919error:
2920
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002921 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002924}
2925
Michal Vasko0d343d12015-08-24 14:57:36 +02002926/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002927static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002928read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002929 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002930{
Radek Krejci76512572015-08-04 09:47:08 +02002931 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002932 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 struct lyxml_elem *sub, *next;
2934 const char *value;
2935 int r;
2936 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002937 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002939 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002940 if (!anyxml) {
2941 LOGMEM;
2942 return NULL;
2943 }
Radek Krejci76512572015-08-04 09:47:08 +02002944 anyxml->nodetype = LYS_ANYXML;
2945 anyxml->prev = (struct lys_node *)anyxml;
2946 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002947
Michal Vaskoe0c59842015-09-24 13:52:20 +02002948 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2949 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 goto error;
2951 }
Radek Krejci863c2852015-06-03 15:47:11 +02002952
Radek Krejcia9544502015-08-14 08:24:29 +02002953 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002954
Radek Krejcic071c542016-01-27 14:57:51 +01002955 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002956 goto error;
2957 }
2958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002960 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2961 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002962 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002963 continue;
2964 }
2965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 if (!strcmp(sub->name, "mandatory")) {
2967 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002968 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969 goto error;
2970 }
2971 /* just checking the flags in leaf is not sufficient, we would allow
2972 * multiple mandatory statements with the "false" value
2973 */
2974 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002976 GETVAL(value, sub, "value");
2977 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002978 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002979 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002980 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002981 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002982 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 goto error;
2984 }
2985 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002986 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002987 } else if (!strcmp(sub->name, "when")) {
2988 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002989 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002990 goto error;
2991 }
2992
2993 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002994 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002995 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002996 goto error;
2997 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002998 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002999 goto error;
3000 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003001 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 } else if (!strcmp(sub->name, "must")) {
3003 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003004 } else if (!strcmp(sub->name, "if-feature")) {
3005 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003008 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 }
3011 }
Radek Krejci863c2852015-06-03 15:47:11 +02003012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 /* middle part - process nodes with cardinality of 0..n */
3014 if (c_must) {
3015 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003016 if (!anyxml->must) {
3017 LOGMEM;
3018 goto error;
3019 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003021 if (c_ftrs) {
3022 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003023 if (!anyxml->features) {
3024 LOGMEM;
3025 goto error;
3026 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003027 }
Radek Krejci863c2852015-06-03 15:47:11 +02003028
Radek Krejci73adb602015-07-02 18:07:40 +02003029 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003031 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3032 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003033 if (r) {
3034 goto error;
3035 }
Michal Vasko0d204592015-10-07 09:50:04 +02003036 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003037 goto error;
3038 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003039 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003040 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003041 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003042 goto error;
3043 }
Radek Krejcicf509982015-12-15 09:22:44 +01003044 /* hack - store pointer to the parent node for later status check */
3045 anyxml->features[anyxml->features_size] = (struct lys_feature *)anyxml;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003046 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003047 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003048 anyxml->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003049 lydict_remove(module->ctx, value);
3050 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003051 goto error;
3052 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003054 }
Radek Krejci863c2852015-06-03 15:47:11 +02003055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003056 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003057
3058error:
3059
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003060 lys_node_free(retval, NULL);
Radek Krejci863c2852015-06-03 15:47:11 +02003061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003063}
3064
Michal Vasko0d343d12015-08-24 14:57:36 +02003065/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003066static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003067read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003068 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003069{
Radek Krejci76512572015-08-04 09:47:08 +02003070 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003071 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 struct lyxml_elem *sub, *next;
3073 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003074 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003075 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003078 if (!leaf) {
3079 LOGMEM;
3080 return NULL;
3081 }
Radek Krejci76512572015-08-04 09:47:08 +02003082 leaf->nodetype = LYS_LEAF;
3083 leaf->prev = (struct lys_node *)leaf;
3084 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003085
Michal Vaskoe0c59842015-09-24 13:52:20 +02003086 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3087 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 goto error;
3089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003090
Radek Krejcia9544502015-08-14 08:24:29 +02003091 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003092
Radek Krejcic071c542016-01-27 14:57:51 +01003093 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003094 goto error;
3095 }
3096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003097 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003098 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3099 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003100 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003101 continue;
3102 }
3103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003105 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003106 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 goto error;
3108 }
Michal Vasko88c29542015-11-27 14:57:53 +01003109 /* HACK for unres */
3110 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003111 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003112 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3113 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003114 goto error;
3115 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003116 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 } else if (!strcmp(sub->name, "default")) {
3118 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003119 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003120 goto error;
3121 }
3122 GETVAL(value, sub, "value");
3123 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003124 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 } else if (!strcmp(sub->name, "units")) {
3126 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003127 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003128 goto error;
3129 }
3130 GETVAL(value, sub, "name");
3131 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3132 } else if (!strcmp(sub->name, "mandatory")) {
3133 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003134 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 goto error;
3136 }
3137 /* just checking the flags in leaf is not sufficient, we would allow
3138 * multiple mandatory statements with the "false" value
3139 */
3140 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 GETVAL(value, sub, "value");
3143 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003144 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003145 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003146 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003147 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003148 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 goto error;
3150 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003151 } else if (!strcmp(sub->name, "when")) {
3152 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003153 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003154 goto error;
3155 }
3156
3157 leaf->when = read_yin_when(module, sub);
3158 if (!leaf->when) {
3159 goto error;
3160 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003161 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003162 goto error;
3163 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003166 c_must++;
3167 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003168 } else if (!strcmp(sub->name, "if-feature")) {
3169 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003173 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003174 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003176
Michal Vasko88c29542015-11-27 14:57:53 +01003177 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003180 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003181 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003182 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 goto error;
3184 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003185 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003186 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003187 goto error;
3188 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003189 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 /* middle part - process nodes with cardinality of 0..n */
3192 if (c_must) {
3193 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003194 if (!leaf->must) {
3195 LOGMEM;
3196 goto error;
3197 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003199 if (c_ftrs) {
3200 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003201 if (!leaf->features) {
3202 LOGMEM;
3203 goto error;
3204 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003205 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003206
Radek Krejci73adb602015-07-02 18:07:40 +02003207 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003209 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3210 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003211 if (r) {
3212 goto error;
3213 }
Michal Vasko0d204592015-10-07 09:50:04 +02003214 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003215 goto error;
3216 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003217 } else if (!strcmp(sub->name, "if-feature")) {
3218 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003219 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003220 goto error;
3221 }
Radek Krejcicf509982015-12-15 09:22:44 +01003222 /* hack - store pointer to the parent node for later status check */
3223 leaf->features[leaf->features_size] = (struct lys_feature *)leaf;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003224 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003225 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003226 leaf->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003227 lydict_remove(module->ctx, value);
3228 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003229 goto error;
3230 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003235
3236error:
3237
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003238 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003241}
3242
Michal Vasko0d343d12015-08-24 14:57:36 +02003243/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003244static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003245read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003246 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003247{
Radek Krejci76512572015-08-04 09:47:08 +02003248 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003249 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 struct lyxml_elem *sub, *next;
3251 const char *value;
3252 char *endptr;
3253 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003254 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003255 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003259 if (!llist) {
3260 LOGMEM;
3261 return NULL;
3262 }
Radek Krejci76512572015-08-04 09:47:08 +02003263 llist->nodetype = LYS_LEAFLIST;
3264 llist->prev = (struct lys_node *)llist;
3265 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003266
Michal Vaskoe0c59842015-09-24 13:52:20 +02003267 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3268 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 goto error;
3270 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003271
Radek Krejcia9544502015-08-14 08:24:29 +02003272 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003273
Radek Krejcic071c542016-01-27 14:57:51 +01003274 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003275 goto error;
3276 }
3277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003279 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3280 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003281 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003282 continue;
3283 }
3284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003286 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003287 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 goto error;
3289 }
Michal Vasko88c29542015-11-27 14:57:53 +01003290 /* HACK for unres */
3291 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003292 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003293 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3294 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003295 goto error;
3296 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003297 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 } else if (!strcmp(sub->name, "units")) {
3299 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003300 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 goto error;
3302 }
3303 GETVAL(value, sub, "name");
3304 llist->units = lydict_insert(module->ctx, value, strlen(value));
3305 } else if (!strcmp(sub->name, "ordered-by")) {
3306 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003307 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 goto error;
3309 }
3310 /* just checking the flags in llist is not sufficient, we would
3311 * allow multiple ordered-by statements with the "system" value
3312 */
3313 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003314
Radek Krejci1574a8d2015-08-03 14:16:52 +02003315 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3317 * state data
3318 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003319 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 continue;
3321 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 GETVAL(value, sub, "value");
3324 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003325 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003327 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003329 } /* else system is the default value, so we can ignore it */
3330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 } else if (!strcmp(sub->name, "must")) {
3332 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003333 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003334 } else if (!strcmp(sub->name, "if-feature")) {
3335 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 } else if (!strcmp(sub->name, "min-elements")) {
3339 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003340 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 goto error;
3342 }
3343 f_min = 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 Krejci6e4ffbb2015-06-16 10:34:41 +02003350 /* convert it to uint32_t */
3351 errno = 0;
3352 endptr = NULL;
3353 val = strtoul(value, &endptr, 10);
3354 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003355 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 goto error;
3357 }
3358 llist->min = (uint32_t) val;
3359 } else if (!strcmp(sub->name, "max-elements")) {
3360 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003361 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 goto error;
3363 }
3364 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 GETVAL(value, sub, "value");
3367 while (isspace(value[0])) {
3368 value++;
3369 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 /* convert it to uint32_t */
3372 errno = 0;
3373 endptr = NULL;
3374 val = strtoul(value, &endptr, 10);
3375 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003376 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003377 goto error;
3378 }
3379 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003380 } else if (!strcmp(sub->name, "when")) {
3381 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003382 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003383 goto error;
3384 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003385
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003386 llist->when = read_yin_when(module, sub);
3387 if (!llist->when) {
3388 goto error;
3389 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003390 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003391 goto error;
3392 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003394 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003397
Michal Vasko88c29542015-11-27 14:57:53 +01003398 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003402 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003403 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 goto error;
3405 }
3406 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003407 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 goto error;
3409 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 /* middle part - process nodes with cardinality of 0..n */
3412 if (c_must) {
3413 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003414 if (!llist->must) {
3415 LOGMEM;
3416 goto error;
3417 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003419 if (c_ftrs) {
3420 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003421 if (!llist->features) {
3422 LOGMEM;
3423 goto error;
3424 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003425 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003426
Radek Krejci73adb602015-07-02 18:07:40 +02003427 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003429 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3430 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 if (r) {
3432 goto error;
3433 }
Michal Vasko0d204592015-10-07 09:50:04 +02003434 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003435 goto error;
3436 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003437 } else if (!strcmp(sub->name, "if-feature")) {
3438 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003439 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003440 goto error;
3441 }
Radek Krejcicf509982015-12-15 09:22:44 +01003442 /* hack - store pointer to the parent node for later status check */
3443 llist->features[llist->features_size] = (struct lys_feature *)llist;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003444 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003445 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003446 llist->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003447 lydict_remove(module->ctx, value);
3448 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003449 goto error;
3450 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003452 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003455
3456error:
3457
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003458 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003461}
3462
Michal Vasko0d343d12015-08-24 14:57:36 +02003463/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003464static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003465read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3466 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003467{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003468 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003469 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003470 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003471 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003472 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003474 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 char *auxs;
3476 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 /* init */
3479 memset(&root, 0, sizeof root);
3480 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003483 if (!list) {
3484 LOGMEM;
3485 return NULL;
3486 }
Radek Krejci76512572015-08-04 09:47:08 +02003487 list->nodetype = LYS_LIST;
3488 list->prev = (struct lys_node *)list;
3489 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003490
Michal Vaskoe0c59842015-09-24 13:52:20 +02003491 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3492 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 goto error;
3494 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003495
Radek Krejcia9544502015-08-14 08:24:29 +02003496 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 /* process list's specific children */
3499 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003500 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3501 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003502 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003503 continue;
3504 }
3505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 /* data statements */
3507 if (!strcmp(sub->name, "container") ||
3508 !strcmp(sub->name, "leaf-list") ||
3509 !strcmp(sub->name, "leaf") ||
3510 !strcmp(sub->name, "list") ||
3511 !strcmp(sub->name, "choice") ||
3512 !strcmp(sub->name, "uses") ||
3513 !strcmp(sub->name, "grouping") ||
3514 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003515 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003516 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 /* array counters */
3519 } else if (!strcmp(sub->name, "key")) {
3520 /* check cardinality 0..1 */
3521 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003522 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003523 goto error;
3524 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 /* count the number of keys */
3527 GETVAL(value, sub, "value");
3528 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003529 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003530 while ((value = strpbrk(value, " \t\n"))) {
3531 list->keys_size++;
3532 while (isspace(*value)) {
3533 value++;
3534 }
3535 }
3536 list->keys_size++;
3537 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003538 if (!list->keys) {
3539 LOGMEM;
3540 goto error;
3541 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 } else if (!strcmp(sub->name, "unique")) {
3543 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003544 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003545 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 } else if (!strcmp(sub->name, "typedef")) {
3547 c_tpdf++;
3548 } else if (!strcmp(sub->name, "must")) {
3549 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003550 } else if (!strcmp(sub->name, "if-feature")) {
3551 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 /* optional stetments */
3554 } else if (!strcmp(sub->name, "ordered-by")) {
3555 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003556 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 goto error;
3558 }
3559 /* just checking the flags in llist is not sufficient, we would
3560 * allow multiple ordered-by statements with the "system" value
3561 */
3562 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003563
Radek Krejci1574a8d2015-08-03 14:16:52 +02003564 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3566 * state data
3567 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003568 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003569 continue;
3570 }
Radek Krejci345ad742015-06-03 11:04:18 +02003571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 GETVAL(value, sub, "value");
3573 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003574 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003576 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 goto error;
3578 }
3579 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003580 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 } else if (!strcmp(sub->name, "min-elements")) {
3582 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003583 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 goto error;
3585 }
3586 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 GETVAL(value, sub, "value");
3589 while (isspace(value[0])) {
3590 value++;
3591 }
Radek Krejci345ad742015-06-03 11:04:18 +02003592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 /* convert it to uint32_t */
3594 errno = 0;
3595 auxs = NULL;
3596 val = strtoul(value, &auxs, 10);
3597 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003598 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 goto error;
3600 }
3601 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003602 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 } else if (!strcmp(sub->name, "max-elements")) {
3604 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003605 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 goto error;
3607 }
3608 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 GETVAL(value, sub, "value");
3611 while (isspace(value[0])) {
3612 value++;
3613 }
Radek Krejci345ad742015-06-03 11:04:18 +02003614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 /* convert it to uint32_t */
3616 errno = 0;
3617 auxs = NULL;
3618 val = strtoul(value, &auxs, 10);
3619 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003620 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 goto error;
3622 }
3623 list->max = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003624 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003625 } else if (!strcmp(sub->name, "when")) {
3626 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003627 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003628 goto error;
3629 }
3630
3631 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003632 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003633 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003634 goto error;
3635 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003636 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003637 goto error;
3638 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003639 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003640 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003641 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003642 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 }
3644 }
Radek Krejci345ad742015-06-03 11:04:18 +02003645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003646 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003647 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003648 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 goto error;
3650 }
3651 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003652 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 goto error;
3654 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3657 if (c_tpdf) {
3658 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003659 if (!list->tpdf) {
3660 LOGMEM;
3661 goto error;
3662 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003664 if (c_must) {
3665 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003666 if (!list->must) {
3667 LOGMEM;
3668 goto error;
3669 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003670 }
3671 if (c_ftrs) {
3672 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003673 if (!list->features) {
3674 LOGMEM;
3675 goto error;
3676 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003677 }
Radek Krejci73adb602015-07-02 18:07:40 +02003678 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003680 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3681 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 if (r) {
3683 goto error;
3684 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003685 } else if (!strcmp(sub->name, "if-feature")) {
3686 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003687 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003688 goto error;
3689 }
Radek Krejcicf509982015-12-15 09:22:44 +01003690 /* hack - store pointer to the parent node for later status check */
3691 list->features[list->features_size] = (struct lys_feature *)list;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003692 r = unres_schema_add_str(module, unres, &list->features[list->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003693 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003694 list->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003695 lydict_remove(module->ctx, value);
3696 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003697 goto error;
3698 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003699 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003700 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3701 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003702 if (r) {
3703 goto error;
3704 }
Michal Vasko0d204592015-10-07 09:50:04 +02003705 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003706 goto error;
3707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 }
3709 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003710
Radek Krejcic071c542016-01-27 14:57:51 +01003711 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003712 goto error;
3713 }
3714
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 /* last part - process data nodes */
3716 LY_TREE_FOR_SAFE(root.child, next, sub) {
3717 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003718 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003719 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003720 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003722 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003723 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003724 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003726 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003728 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003730 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003732 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003733 } else {
3734 LOGINT;
3735 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003737 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 goto error;
3739 }
Radek Krejci73adb602015-07-02 18:07:40 +02003740
Michal Vasko345da0a2015-12-02 10:35:55 +01003741 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 if (!key_str) {
3745 /* config false list without a key */
3746 return retval;
3747 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003748 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003749 goto error;
3750 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 /* process unique statements */
3753 if (c_uniq) {
3754 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003755 if (!list->unique) {
3756 LOGMEM;
3757 goto error;
3758 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 }
3760 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003761 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3762 list->unique_size++;
3763 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003764 goto error;
3765 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003766
Michal Vasko345da0a2015-12-02 10:35:55 +01003767 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003768 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003771
3772error:
3773
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003774 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003775 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003776 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 }
3778 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003779 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003782 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003783}
3784
Michal Vasko0d343d12015-08-24 14:57:36 +02003785/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003786static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003787read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3788 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003789{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003791 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003792 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003793 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003794 const char *value;
3795 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003796 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 /* init */
3799 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003802 if (!cont) {
3803 LOGMEM;
3804 return NULL;
3805 }
Radek Krejci76512572015-08-04 09:47:08 +02003806 cont->nodetype = LYS_CONTAINER;
3807 cont->prev = (struct lys_node *)cont;
3808 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003809
Michal Vaskoe0c59842015-09-24 13:52:20 +02003810 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3811 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 goto error;
3813 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003814
Radek Krejcia9544502015-08-14 08:24:29 +02003815 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 /* process container's specific children */
3818 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003819 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003820 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003821 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003822 continue;
3823 }
3824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003825 if (!strcmp(sub->name, "presence")) {
3826 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003827 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 goto error;
3829 }
3830 GETVAL(value, sub, "value");
3831 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003832
Michal Vasko345da0a2015-12-02 10:35:55 +01003833 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003834 } else if (!strcmp(sub->name, "when")) {
3835 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003836 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003837 goto error;
3838 }
3839
3840 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003841 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003842 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003843 goto error;
3844 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003845 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003846 goto error;
3847 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003848 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 /* data statements */
3851 } else if (!strcmp(sub->name, "container") ||
3852 !strcmp(sub->name, "leaf-list") ||
3853 !strcmp(sub->name, "leaf") ||
3854 !strcmp(sub->name, "list") ||
3855 !strcmp(sub->name, "choice") ||
3856 !strcmp(sub->name, "uses") ||
3857 !strcmp(sub->name, "grouping") ||
3858 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003859 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003860 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 /* array counters */
3863 } else if (!strcmp(sub->name, "typedef")) {
3864 c_tpdf++;
3865 } else if (!strcmp(sub->name, "must")) {
3866 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003867 } else if (!strcmp(sub->name, "if-feature")) {
3868 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003870 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 }
3873 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3876 if (c_tpdf) {
3877 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003878 if (!cont->tpdf) {
3879 LOGMEM;
3880 goto error;
3881 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 }
3883 if (c_must) {
3884 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003885 if (!cont->must) {
3886 LOGMEM;
3887 goto error;
3888 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003890 if (c_ftrs) {
3891 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003892 if (!cont->features) {
3893 LOGMEM;
3894 goto error;
3895 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003896 }
Radek Krejci800af702015-06-02 13:46:01 +02003897
Radek Krejci73adb602015-07-02 18:07:40 +02003898 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003900 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3901 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 if (r) {
3903 goto error;
3904 }
3905 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003906 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3907 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003908 if (r) {
3909 goto error;
3910 }
Michal Vasko0d204592015-10-07 09:50:04 +02003911 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003912 goto error;
3913 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003914 } else if (!strcmp(sub->name, "if-feature")) {
3915 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003916 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003917 goto error;
3918 }
Radek Krejcicf509982015-12-15 09:22:44 +01003919 /* hack - store pointer to the parent node for later status check */
3920 cont->features[cont->features_size] = (struct lys_feature *)cont;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003921 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003922 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003923 cont->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003924 lydict_remove(module->ctx, value);
3925 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003926 goto error;
3927 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003930
Radek Krejcic071c542016-01-27 14:57:51 +01003931 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003932 goto error;
3933 }
3934
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 /* last part - process data nodes */
3936 LY_TREE_FOR_SAFE(root.child, next, sub) {
3937 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003938 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003939 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003940 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003941 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003942 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003944 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003946 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003948 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003950 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 goto error;
3956 }
Radek Krejci73adb602015-07-02 18:07:40 +02003957
Michal Vasko345da0a2015-12-02 10:35:55 +01003958 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003962
3963error:
3964
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003965 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003967 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003970 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003971}
3972
Michal Vasko0d343d12015-08-24 14:57:36 +02003973/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003974static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003975read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003976 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003977{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003978 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003979 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003980 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003981 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003982 int r;
3983 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 /* init */
3986 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003987
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003988 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003989 if (!grp) {
3990 LOGMEM;
3991 return NULL;
3992 }
Radek Krejci76512572015-08-04 09:47:08 +02003993 grp->nodetype = LYS_GROUPING;
3994 grp->prev = (struct lys_node *)grp;
3995 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003996
Michal Vasko71e1aa82015-08-12 12:17:51 +02003997 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 goto error;
3999 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004000
Radek Krejcia9544502015-08-14 08:24:29 +02004001 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4002
Radek Krejci1d82ef62015-08-07 14:44:40 +02004003 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004004 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4005 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004006 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004007 continue;
4008 }
4009
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004010 /* data statements */
4011 if (!strcmp(sub->name, "container") ||
4012 !strcmp(sub->name, "leaf-list") ||
4013 !strcmp(sub->name, "leaf") ||
4014 !strcmp(sub->name, "list") ||
4015 !strcmp(sub->name, "choice") ||
4016 !strcmp(sub->name, "uses") ||
4017 !strcmp(sub->name, "grouping") ||
4018 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004019 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004020 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004022 /* array counters */
4023 } else if (!strcmp(sub->name, "typedef")) {
4024 c_tpdf++;
4025 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004026 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 goto error;
4028 }
4029 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004031 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4032 if (c_tpdf) {
4033 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004034 if (!grp->tpdf) {
4035 LOGMEM;
4036 goto error;
4037 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004038 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004039 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004040 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4041 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004042 if (r) {
4043 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004044 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004046
Radek Krejcic071c542016-01-27 14:57:51 +01004047 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004048 goto error;
4049 }
4050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 /* last part - process data nodes */
4052 LY_TREE_FOR_SAFE(root.child, next, sub) {
4053 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004054 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004055 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004056 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004057 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004058 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004059 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004060 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004062 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004063 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004064 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004065 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004066 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004067 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004068 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004069 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004070 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004071 goto error;
4072 }
Radek Krejci73adb602015-07-02 18:07:40 +02004073
Michal Vasko345da0a2015-12-02 10:35:55 +01004074 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004075 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004077 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004078
4079error:
4080
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004081 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004082 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004083 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004084 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004086 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004087}
4088
Michal Vasko0d343d12015-08-24 14:57:36 +02004089/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004090static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004091read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4092 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004093{
Radek Krejcie0674f82015-06-15 13:58:51 +02004094 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004095 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004096 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004097 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004098 int r;
4099 int c_tpdf = 0;
4100
Radek Krejcie0674f82015-06-15 13:58:51 +02004101 /* init */
4102 memset(&root, 0, sizeof root);
4103
Michal Vasko38d01f72015-06-15 09:41:06 +02004104 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004105 if (!inout) {
4106 LOGMEM;
4107 return NULL;
4108 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004109 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004110
4111 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004112 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004113 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004114 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004115 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004116 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004117 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004118 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004119 }
4120
Radek Krejci76512572015-08-04 09:47:08 +02004121 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004122
Radek Krejci6a113852015-07-03 16:04:20 +02004123 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004124 goto error;
4125 }
4126
Radek Krejcia9544502015-08-14 08:24:29 +02004127 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4128
Michal Vasko38d01f72015-06-15 09:41:06 +02004129 /* data statements */
4130 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004131 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4132 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004133 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004134 continue;
4135 }
4136
Michal Vasko38d01f72015-06-15 09:41:06 +02004137 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004138 !strcmp(sub->name, "leaf-list") ||
4139 !strcmp(sub->name, "leaf") ||
4140 !strcmp(sub->name, "list") ||
4141 !strcmp(sub->name, "choice") ||
4142 !strcmp(sub->name, "uses") ||
4143 !strcmp(sub->name, "grouping") ||
4144 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004145 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004146 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004148 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004149 } else if (!strcmp(sub->name, "typedef")) {
4150 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004151
Michal Vasko38d01f72015-06-15 09:41:06 +02004152 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004153 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004154 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 }
4156 }
4157
4158 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4159 if (c_tpdf) {
4160 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004161 if (!inout->tpdf) {
4162 LOGMEM;
4163 goto error;
4164 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004165 }
4166
Radek Krejci73adb602015-07-02 18:07:40 +02004167 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004168 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4169 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004170 if (r) {
4171 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004172 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 }
4174
Radek Krejcic071c542016-01-27 14:57:51 +01004175 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004176 goto error;
4177 }
4178
Michal Vasko38d01f72015-06-15 09:41:06 +02004179 /* last part - process data nodes */
4180 LY_TREE_FOR_SAFE(root.child, next, sub) {
4181 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004182 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004183 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004184 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004185 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004186 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004187 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004188 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004189 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004190 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004191 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004192 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004193 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004194 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004195 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004196 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004197 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004198 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004199 goto error;
4200 }
Radek Krejci73adb602015-07-02 18:07:40 +02004201
Michal Vasko345da0a2015-12-02 10:35:55 +01004202 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004203 }
4204
Michal Vasko38d01f72015-06-15 09:41:06 +02004205 return retval;
4206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004208
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004209 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004210 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004211 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004212 }
4213
4214 return NULL;
4215}
4216
Michal Vasko0d343d12015-08-24 14:57:36 +02004217/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004218static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004219read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4220 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004221{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004222 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004223 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004224 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004225 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004226 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004227 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004228 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004229
Michal Vaskoc6551b32015-06-16 10:51:43 +02004230 memset(&root, 0, sizeof root);
4231
Michal Vasko0ea41032015-06-16 08:53:55 +02004232 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004233 if (!notif) {
4234 LOGMEM;
4235 return NULL;
4236 }
Radek Krejci76512572015-08-04 09:47:08 +02004237 notif->nodetype = LYS_NOTIF;
4238 notif->prev = (struct lys_node *)notif;
4239 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004240
Radek Krejci6a113852015-07-03 16:04:20 +02004241 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 goto error;
4243 }
4244
Radek Krejcia9544502015-08-14 08:24:29 +02004245 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4246
Michal Vasko0ea41032015-06-16 08:53:55 +02004247 /* process rpc's specific children */
4248 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004249 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4250 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004251 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004252 continue;
4253 }
4254
Michal Vasko0ea41032015-06-16 08:53:55 +02004255 /* data statements */
4256 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004257 !strcmp(sub->name, "leaf-list") ||
4258 !strcmp(sub->name, "leaf") ||
4259 !strcmp(sub->name, "list") ||
4260 !strcmp(sub->name, "choice") ||
4261 !strcmp(sub->name, "uses") ||
4262 !strcmp(sub->name, "grouping") ||
4263 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004264 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004265 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004267 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004268 } else if (!strcmp(sub->name, "typedef")) {
4269 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004270 } else if (!strcmp(sub->name, "if-feature")) {
4271 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004272 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004273 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004274 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004275 }
4276 }
4277
4278 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4279 if (c_tpdf) {
4280 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004281 if (!notif->tpdf) {
4282 LOGMEM;
4283 goto error;
4284 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004285 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004286 if (c_ftrs) {
4287 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004288 if (!notif->features) {
4289 LOGMEM;
4290 goto error;
4291 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004292 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004293
Radek Krejci73adb602015-07-02 18:07:40 +02004294 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004295 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004296 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4297 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004298 if (r) {
4299 goto error;
4300 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004301 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004302 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004303 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004304 goto error;
4305 }
Radek Krejcicf509982015-12-15 09:22:44 +01004306 /* hack - store pointer to the parent node for later status check */
4307 notif->features[notif->features_size] = (struct lys_feature *)notif;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004308 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004309 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004310 notif->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004311 lydict_remove(module->ctx, value);
4312 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004313 goto error;
4314 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004315 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004316 }
4317
Radek Krejcic071c542016-01-27 14:57:51 +01004318 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004319 goto error;
4320 }
4321
Michal Vasko0ea41032015-06-16 08:53:55 +02004322 /* last part - process data nodes */
4323 LY_TREE_FOR_SAFE(root.child, next, sub) {
4324 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004325 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004326 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004327 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004328 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004329 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004330 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004331 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004332 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004333 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004334 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004335 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004336 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004337 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004338 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004339 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004340 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004341 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004342 goto error;
4343 }
Radek Krejci73adb602015-07-02 18:07:40 +02004344
Michal Vasko345da0a2015-12-02 10:35:55 +01004345 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004346 }
4347
Michal Vasko0ea41032015-06-16 08:53:55 +02004348 return retval;
4349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004351
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004352 lys_node_free(retval, NULL);
Michal Vasko0ea41032015-06-16 08:53:55 +02004353 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004354 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004355 }
4356
4357 return NULL;
4358}
4359
Michal Vasko0d343d12015-08-24 14:57:36 +02004360/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004361static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004362read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4363 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004364{
Radek Krejcie0674f82015-06-15 13:58:51 +02004365 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004366 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004367 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004368 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004369 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004370 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004371 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004372
Radek Krejcie0674f82015-06-15 13:58:51 +02004373 /* init */
4374 memset(&root, 0, sizeof root);
4375
Michal Vasko38d01f72015-06-15 09:41:06 +02004376 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004377 if (!rpc) {
4378 LOGMEM;
4379 return NULL;
4380 }
Radek Krejci76512572015-08-04 09:47:08 +02004381 rpc->nodetype = LYS_RPC;
4382 rpc->prev = (struct lys_node *)rpc;
4383 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004384
Radek Krejci6a113852015-07-03 16:04:20 +02004385 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004386 goto error;
4387 }
4388
Radek Krejcia9544502015-08-14 08:24:29 +02004389 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4390
Michal Vasko38d01f72015-06-15 09:41:06 +02004391 /* process rpc's specific children */
4392 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004393 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4394 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004395 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004396 continue;
4397 }
4398
Michal Vasko38d01f72015-06-15 09:41:06 +02004399 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004401 && (rpc->child->nodetype == LYS_INPUT
4402 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004403 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004404 goto error;
4405 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004406 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004407 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004408 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004410 && (rpc->child->nodetype == LYS_INPUT
4411 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004412 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004413 goto error;
4414 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004415 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004416 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004419 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004420 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004421 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004424 } else if (!strcmp(sub->name, "typedef")) {
4425 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004426 } else if (!strcmp(sub->name, "if-feature")) {
4427 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004428 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004429 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004430 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004431 }
4432 }
4433
4434 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4435 if (c_tpdf) {
4436 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004437 if (!rpc->tpdf) {
4438 LOGMEM;
4439 goto error;
4440 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004441 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004442 if (c_ftrs) {
4443 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004444 if (!rpc->features) {
4445 LOGMEM;
4446 goto error;
4447 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004448 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004449
Radek Krejci73adb602015-07-02 18:07:40 +02004450 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004451 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004452 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4453 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004454 if (r) {
4455 goto error;
4456 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004457 } else if (!strcmp(sub->name, "if-feature")) {
4458 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004459 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004460 goto error;
4461 }
Radek Krejcicf509982015-12-15 09:22:44 +01004462 /* hack - store pointer to the parent node for later status check */
4463 rpc->features[rpc->features_size] = (struct lys_feature *)rpc;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004464 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004465 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004466 rpc->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004467 lydict_remove(module->ctx, value);
4468 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004469 goto error;
4470 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004471 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004472 }
4473
Radek Krejcic071c542016-01-27 14:57:51 +01004474 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004475 goto error;
4476 }
4477
Michal Vasko38d01f72015-06-15 09:41:06 +02004478 /* last part - process data nodes */
4479 LY_TREE_FOR_SAFE(root.child, next, sub) {
4480 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004481 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004482 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004483 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004484 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004485 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004486 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004487 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004488 goto error;
4489 }
Radek Krejci73adb602015-07-02 18:07:40 +02004490
Michal Vasko345da0a2015-12-02 10:35:55 +01004491 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004492 }
4493
Michal Vasko38d01f72015-06-15 09:41:06 +02004494 return retval;
4495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004497
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004498 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004499 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004500 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004501 }
4502
4503 return NULL;
4504}
4505
Michal Vasko0d343d12015-08-24 14:57:36 +02004506/* logs directly
4507 *
Radek Krejci74705112015-06-05 10:25:44 +02004508 * resolve - referenced grouping should be bounded to the namespace (resolved)
4509 * only when uses does not appear in grouping. In a case of grouping's uses,
4510 * we just get information but we do not apply augment or refine to it.
4511 */
Radek Krejci76512572015-08-04 09:47:08 +02004512static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004513read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004514 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004515{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004517 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004518 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004520 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004524 if (!uses) {
4525 LOGMEM;
4526 return NULL;
4527 }
Radek Krejci76512572015-08-04 09:47:08 +02004528 uses->nodetype = LYS_USES;
4529 uses->prev = (struct lys_node *)uses;
4530 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004531
Radek Krejcia9544502015-08-14 08:24:29 +02004532 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004534
Michal Vaskoe0c59842015-09-24 13:52:20 +02004535 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4536 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 goto error;
4538 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004539
Radek Krejcia9544502015-08-14 08:24:29 +02004540 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004543 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004544 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4545 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004546 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004547 continue;
4548 }
4549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 if (!strcmp(sub->name, "refine")) {
4551 c_ref++;
4552 } else if (!strcmp(sub->name, "augment")) {
4553 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004554 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004555 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004556 } else if (!strcmp(sub->name, "when")) {
4557 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004558 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004559 goto error;
4560 }
4561
4562 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004563 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004564 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004565 goto error;
4566 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004567 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004568 goto error;
4569 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004570 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004572 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 }
4575 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 /* process properties with cardinality 0..n */
4578 if (c_ref) {
4579 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004580 if (!uses->refine) {
4581 LOGMEM;
4582 goto error;
4583 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 }
4585 if (c_aug) {
4586 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004587 if (!uses->augment) {
4588 LOGMEM;
4589 goto error;
4590 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004592 if (c_ftrs) {
4593 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004594 if (!uses->features) {
4595 LOGMEM;
4596 goto error;
4597 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004598 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004599
Radek Krejcic071c542016-01-27 14:57:51 +01004600 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004601 goto error;
4602 }
4603
Radek Krejcia9544502015-08-14 08:24:29 +02004604 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004606 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4607 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004608 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004609 goto error;
4610 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004611 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004612 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4613 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004614 if (r) {
4615 goto error;
4616 }
4617 } else if (!strcmp(sub->name, "if-feature")) {
4618 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004619 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004620 goto error;
4621 }
Radek Krejcicf509982015-12-15 09:22:44 +01004622 /* hack - store pointer to the parent node for later status check */
4623 uses->features[uses->features_size] = (struct lys_feature *)uses;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004624 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02004625 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004626 uses->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004627 lydict_remove(module->ctx, value);
4628 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004629 goto error;
4630 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 }
4632 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004633
Michal Vasko0bd29d12015-08-19 11:45:49 +02004634 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004635 goto error;
4636 }
Radek Krejci74705112015-06-05 10:25:44 +02004637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 if (resolve) {
4639 /* inherit config flag */
4640 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004641 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 } else {
4643 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004644 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 }
4646 }
Radek Krejcib388c152015-06-04 17:03:03 +02004647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004649
4650error:
4651
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004652 lys_node_free(retval, NULL);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004655}
4656
Michal Vasko0d343d12015-08-24 14:57:36 +02004657/* logs directly
4658 *
4659 * common code for yin_read_module() and yin_read_submodule()
4660 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661static int
Radek Krejcic071c542016-01-27 14:57:51 +01004662read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4663 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004664{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004666 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004667 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004668 struct lys_module *trg;
4669 struct lys_import *aux_imp;
4670 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004672 int i, j, r;
4673 int inc_size_aux = 0;
4674 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004675 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004676 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 +02004677
Radek Krejcic071c542016-01-27 14:57:51 +01004678 /* to simplify code, store the module/submodule being processed as trg */
4679 trg = submodule ? (struct lys_module*)submodule : module;
4680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 /* init */
4682 memset(&root, 0, sizeof root);
4683 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004684 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 /*
4687 * in the first run, we process elements with cardinality of 1 or 0..1 and
4688 * count elements with cardinality 0..n. Data elements (choices, containers,
4689 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4690 * need have all top-level and groupings already prepared at that time. In
4691 * the middle loop, we process other elements with carinality of 0..n since
4692 * we need to allocate arrays to store them.
4693 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004694 LY_TREE_FOR_SAFE(yin->child, next, child) {
4695 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004696 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004697 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 continue;
4699 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004700
Radek Krejcic071c542016-01-27 14:57:51 +01004701 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004703 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 goto error;
4705 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004706 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004708 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004709 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004711 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004712 goto error;
4713 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004714 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004715 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 goto error;
4717 }
4718 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004719 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004720 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4721 if (submodule->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004722 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004723 goto error;
4724 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004725 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004727 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 goto error;
4729 }
Radek Krejcif3886932015-06-04 17:36:06 +02004730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004732 if (!child->child) {
4733 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004735 } else if (strcmp(child->child->name, "prefix")) {
4736 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004738 } else if (child->child->next) {
4739 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 goto error;
4741 }
4742 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004743 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 /* check here differs from a generic prefix check, since this prefix
4745 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004746 */
Radek Krejcic6556022016-01-27 15:16:45 +01004747 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 goto error;
4749 }
Radek Krejcic071c542016-01-27 14:57:51 +01004750 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004753 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004754
4755 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004756 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004758 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004759 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004760 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004762 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004763 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004764 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004766 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004767 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004768 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004769 lyxml_unlink_elem(ctx, child, 2);
4770 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004771
Radek Krejci1d82ef62015-08-07 14:44:40 +02004772 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004773 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004775 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004778 } else if (!strcmp(child->name, "container") ||
4779 !strcmp(child->name, "leaf-list") ||
4780 !strcmp(child->name, "leaf") ||
4781 !strcmp(child->name, "list") ||
4782 !strcmp(child->name, "choice") ||
4783 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004784 !strcmp(child->name, "anyxml") ||
4785 !strcmp(child->name, "rpc") ||
4786 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004787 lyxml_unlink_elem(ctx, child, 2);
4788 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004789
Radek Krejci1d82ef62015-08-07 14:44:40 +02004790 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004792 lyxml_unlink_elem(ctx, child, 2);
4793 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004795 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004796 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004797 if (trg->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004798 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 goto error;
4800 }
Radek Krejcic071c542016-01-27 14:57:51 +01004801 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004802 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004803 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 goto error;
4805 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004806 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004807 if (trg->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004808 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 goto error;
4810 }
Radek Krejcic071c542016-01-27 14:57:51 +01004811 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004812 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004813 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814 goto error;
4815 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004816 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004817 if (trg->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004818 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004819 goto error;
4820 }
Radek Krejcic071c542016-01-27 14:57:51 +01004821 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004822 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004823 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 goto error;
4825 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004826 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004827 if (trg->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004828 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004829 goto error;
4830 }
Radek Krejcic071c542016-01-27 14:57:51 +01004831 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004832 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004833 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004834 goto error;
4835 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004836 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004838 if (version_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004839 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004840 goto error;
4841 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004842 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004843 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004844 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 goto error;
4846 }
Radek Krejcic071c542016-01-27 14:57:51 +01004847 version_flag = 1;
4848 if (!submodule) {
4849 module->version = 1;
4850 } /* 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 +01004851 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004852
Radek Krejci1d82ef62015-08-07 14:44:40 +02004853 } else if (!strcmp(child->name, "extension")) {
4854 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004855
Radek Krejci3d468122015-10-02 13:36:12 +02004856 /* we have the following supported (hardcoded) extensions: */
4857 /* ietf-netconf's get-filter-element-attributes */
4858 if (!strcmp(module->ns, LY_NSNC) &&
4859 !strcmp(value, "get-filter-element-attributes")) {
4860 LOGDBG("NETCONF filter extension found");
4861 /* NACM's default-deny-write and default-deny-all */
4862 } else if (!strcmp(module->ns, LY_NSNACM) &&
4863 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4864 LOGDBG("NACM extension found");
4865 /* other extensions are not supported, so inform about such an extension */
4866 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004867 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004868 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004869 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004871 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004873 }
4874 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004875
Radek Krejcic071c542016-01-27 14:57:51 +01004876 /* check for mandatory statements */
4877 if (submodule && !submodule->prefix) {
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004878 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "belongs-to", "submodule");
4879 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004880 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004882 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 goto error;
4884 }
4885 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004886 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 goto error;
4888 }
4889 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 /* allocate arrays for elements with cardinality of 0..n */
4892 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004893 trg->imp = calloc(c_imp, sizeof *trg->imp);
4894 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004895 LOGMEM;
4896 goto error;
4897 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 }
4899 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004900 trg->rev = calloc(c_rev, sizeof *trg->rev);
4901 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004902 LOGMEM;
4903 goto error;
4904 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 }
4906 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004907 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4908 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004909 LOGMEM;
4910 goto error;
4911 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 }
4913 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004914 trg->ident = calloc(c_ident, sizeof *trg->ident);
4915 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004916 LOGMEM;
4917 goto error;
4918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 }
4920 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004921 trg->inc = calloc(c_inc, sizeof *trg->inc);
4922 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004923 LOGMEM;
4924 goto error;
4925 }
Radek Krejcic071c542016-01-27 14:57:51 +01004926 trg->inc_size = c_inc;
4927 /* trg->inc_size can be updated by the included submodules,
4928 * so we will use inc_size_aux here, trg->inc_size stores the
4929 * target size of the array
4930 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004931 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004932 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004933 trg->augment = calloc(c_aug, sizeof *trg->augment);
4934 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004935 LOGMEM;
4936 goto error;
4937 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004938 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004939 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004940 trg->features = calloc(c_ftrs, sizeof *trg->features);
4941 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004942 LOGMEM;
4943 goto error;
4944 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004945 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004946 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004947 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4948 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004949 LOGMEM;
4950 goto error;
4951 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004952 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004953
Michal Vasko2f7925f2015-10-21 15:06:56 +02004954 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4955 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004956 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004957 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4958 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004959 if (r) {
4960 goto error;
4961 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004963 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004964 for (i = 0; i < trg->imp_size - 1; i++) {
4965 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
4966 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 goto error;
4968 }
4969 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004970
Radek Krejci1d82ef62015-08-07 14:44:40 +02004971 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004972 memset(&inc, 0, sizeof inc);
4973 /* 1) pass module, not trg, since we want to pass the main module
4974 * 2) we cannot pass directly the structure in the array since
4975 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004976 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004977 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4978 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 if (r) {
4980 goto error;
4981 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004984 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01004985 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004986 LOGVAL(LYE_SPEC, LOGLINE(child), "Including submodule \"%s\" repeatedly.",
Michal Vasko27ab8222016-02-12 09:33:52 +01004987 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 goto error;
4989 }
4990 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004991
Radek Krejci1d82ef62015-08-07 14:44:40 +02004992 } else if (!strcmp(child->name, "revision")) {
4993 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004994 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004995 goto error;
4996 }
Radek Krejcic071c542016-01-27 14:57:51 +01004997 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004998 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004999 for (i = 0; i < trg->rev_size; i++) {
5000 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005001 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005002 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 }
5004 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005005
Radek Krejci1d82ef62015-08-07 14:44:40 +02005006 LY_TREE_FOR(child->child, child2) {
5007 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005008 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005009 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 goto error;
5011 }
Radek Krejcic071c542016-01-27 14:57:51 +01005012 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5013 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005014 goto error;
5015 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005016 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005017 if (trg->rev[trg->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005018 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 goto error;
5020 }
Radek Krejcic071c542016-01-27 14:57:51 +01005021 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5022 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 goto error;
5024 }
5025 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005026 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 goto error;
5028 }
5029 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005031 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005032 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005033 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005034 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005035 if (!value) {
5036 LOGMEM;
5037 goto error;
5038 }
Radek Krejcic071c542016-01-27 14:57:51 +01005039 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5040 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005041 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005042
Radek Krejcic071c542016-01-27 14:57:51 +01005043 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
5044 value = trg->rev[0].dsc;
5045 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5046 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005048
Radek Krejcic071c542016-01-27 14:57:51 +01005049 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
5050 value = trg->rev[0].ref;
5051 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5052 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005053 }
5054 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005055
Radek Krejcic071c542016-01-27 14:57:51 +01005056 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005057
Radek Krejci1d82ef62015-08-07 14:44:40 +02005058 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005059 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5060 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005061 if (r) {
5062 goto error;
5063 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005064
Radek Krejci1d82ef62015-08-07 14:44:40 +02005065 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005066 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5067 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005068 if (r) {
5069 goto error;
5070 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005071
Radek Krejci1d82ef62015-08-07 14:44:40 +02005072 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005073 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5074 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005075 if (r) {
5076 goto error;
5077 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005078
Radek Krejci1d82ef62015-08-07 14:44:40 +02005079 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005080 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5081 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005082 if (r) {
5083 goto error;
5084 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005086 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005087 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005088
Radek Krejcic071c542016-01-27 14:57:51 +01005089 if (submodule) {
5090 /* propagate imports into the main module */
5091 for (i = r = 0; i < submodule->imp_size; i++) {
5092 for (j = 0; j < module->imp_size; j++) {
5093 if (submodule->imp[i].module == module->imp[j].module &&
5094 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5095 /* check prefix match */
5096 if (submodule->imp[i].prefix != module->imp[j].prefix) {
5097 LOGVAL(LYE_INID, LOGLINE(yin), submodule->imp[i].prefix,
5098 "non-matching prefixes of imported module in main module and submodule");
5099 goto error;
5100 }
5101 break;
5102 }
5103 }
5104 if (j == module->imp_size) {
5105 /* new import */
5106 r++;
5107 }
5108 }
5109 if (r) {
5110 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5111 if (!aux_imp) {
5112 LOGMEM;
5113 goto error;
5114 }
5115 module->imp = aux_imp;
5116 for (i = r = 0; i < submodule->imp_size; i++) {
5117 for (j = 0; j < module->imp_size; j++) {
5118 if (submodule->imp[i].module == module->imp[j].module) {
5119 break;
5120 }
5121 }
5122 if (j == module->imp_size) {
5123 /* new import */
5124 /* check prefix uniqueness */
5125 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
5126 LOGVAL(LYE_DUPID, LOGLINE(yin), "prefix", submodule->imp[i].prefix);
5127 goto error;
5128 }
5129 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5130 module->imp[module->imp_size + r].external = 1;
5131 r++;
5132 }
5133 }
5134 module->imp_size += r;
5135 }
5136
Michal Vaskoe2905632016-02-11 15:42:24 +01005137 /* propagate includes into the main module */
Radek Krejcic071c542016-01-27 14:57:51 +01005138 for (i = r = 0; i < submodule->inc_size; i++) {
5139 for (j = 0; j < module->inc_size; j++) {
5140 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5141 break;
5142 }
5143 }
5144 if (j == module->inc_size) {
5145 /* new include */
5146 r++;
5147 }
5148 }
5149
5150 if (r) {
5151 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5152 if (!aux_inc) {
5153 LOGMEM;
5154 goto error;
5155 }
5156 module->inc = aux_inc;
5157 for (i = r = 0; i < submodule->inc_size; i++) {
5158 for (j = 0; j < module->inc_size; j++) {
5159 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5160 break;
5161 }
5162 }
5163 if (j == module->inc_size) {
5164 /* new include */
5165 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5166 module->inc[module->inc_size + r].external = 1;
5167 r++;
5168 }
5169 }
5170 module->inc_size += r;
5171 }
5172 }
5173
Radek Krejcif5be10f2015-06-16 13:29:36 +02005174 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005175 * refer to them. Submodule's data nodes are stored in the
5176 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005177 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005178 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005179 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005180 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 goto error;
5182 }
Radek Krejci74705112015-06-05 10:25:44 +02005183
Michal Vasko345da0a2015-12-02 10:35:55 +01005184 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 }
Radek Krejci74705112015-06-05 10:25:44 +02005186
Radek Krejcif5be10f2015-06-16 13:29:36 +02005187 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005188 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005189
Radek Krejci1d82ef62015-08-07 14:44:40 +02005190 if (!strcmp(child->name, "container")) {
5191 node = read_yin_container(module, NULL, child, 1, unres);
5192 } else if (!strcmp(child->name, "leaf-list")) {
5193 node = read_yin_leaflist(module, NULL, child, 1, unres);
5194 } else if (!strcmp(child->name, "leaf")) {
5195 node = read_yin_leaf(module, NULL, child, 1, unres);
5196 } else if (!strcmp(child->name, "list")) {
5197 node = read_yin_list(module, NULL, child, 1, unres);
5198 } else if (!strcmp(child->name, "choice")) {
5199 node = read_yin_choice(module, NULL, child, 1, unres);
5200 } else if (!strcmp(child->name, "uses")) {
5201 node = read_yin_uses(module, NULL, child, 1, unres);
5202 } else if (!strcmp(child->name, "anyxml")) {
5203 node = read_yin_anyxml(module, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005204 } else if (!strcmp(child->name, "rpc")) {
5205 node = read_yin_rpc(module, NULL, child, 0, unres);
5206 } else if (!strcmp(child->name, "notification")) {
5207 node = read_yin_notif(module, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005209 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005210 goto error;
5211 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005212
Michal Vasko345da0a2015-12-02 10:35:55 +01005213 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005214 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005215
Michal Vasko2f7925f2015-10-21 15:06:56 +02005216 /* ... and finally augments (last, so we can augment our data, for instance) */
5217 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005218 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5219 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005220
Michal Vasko2f7925f2015-10-21 15:06:56 +02005221 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005222 goto error;
5223 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005224 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005225 }
5226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005227 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005228
5229error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 /* cleanup */
5231 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005232 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 }
5234 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005235 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005236 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005237 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005238 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005239 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005241 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005242}
5243
Michal Vasko0d343d12015-08-24 14:57:36 +02005244/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005245struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01005246yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005247{
Michal Vasko9f258e42016-02-11 11:36:27 +01005248 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005250 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005251 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005252 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005255
Radek Krejci722b0072016-02-01 17:09:45 +01005256 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 if (!yin) {
5258 return NULL;
5259 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 /* check root element */
5262 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005263 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 goto error;
5265 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005267 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005268 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 goto error;
5270 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 submodule = calloc(1, sizeof *submodule);
5273 if (!submodule) {
5274 LOGMEM;
5275 goto error;
5276 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 submodule->ctx = module->ctx;
5279 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5280 submodule->type = 1;
5281 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005282
Michal Vasko9f258e42016-02-11 11:36:27 +01005283 LOGVRB("Reading submodule \"%s\".", submodule->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005284 if (read_sub_module(module, submodule, yin, unres)) {
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 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005289 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005290
Michal Vasko9f258e42016-02-11 11:36:27 +01005291 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005294
5295error:
Michal Vasko9f258e42016-02-11 11:36:27 +01005296 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
5297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005299 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005300 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005301
5302 /* warn about applied deviations */
5303 for (i = 0; i < submodule->deviation_size; ++i) {
5304 if (submodule->deviation[i].target) {
5305 LOGERR(ly_errno, "Submodule parsing failed, but successfully deviated %smodule \"%s\".",
5306 (submodule->deviation[i].target->module->type ? "sub" : ""),
5307 submodule->deviation[i].target->module->name);
5308 }
5309 }
5310
5311 /* remove applied augments */
5312 for (i = 0; i < submodule->augment_size; ++i) {
5313 if (submodule->augment[i].target) {
5314 LY_TREE_FOR_SAFE(submodule->augment[i].target->child, next, elem) {
5315 if (elem->parent == (struct lys_node *)&submodule->augment[i]) {
5316 lys_node_free(elem, NULL);
5317 }
5318 }
5319 }
5320 }
5321
5322 lys_submodule_free(submodule, NULL);
Radek Krejciefaeba32015-05-27 14:30:57 +02005323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005324 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005325}
5326
Michal Vasko0d343d12015-08-24 14:57:36 +02005327/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005328struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005329yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005330{
Michal Vasko9f258e42016-02-11 11:36:27 +01005331 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005332 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005333 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005334 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005335 const char *value;
5336 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005337
Radek Krejcic071c542016-01-27 14:57:51 +01005338 unres = calloc(1, sizeof *unres);
5339 if (!unres) {
5340 LOGMEM;
5341 return NULL;
5342 }
5343
Radek Krejci722b0072016-02-01 17:09:45 +01005344 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005345 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005346 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005347 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005349 /* check root element */
5350 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005351 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005352 goto error;
5353 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005356 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 goto error;
5358 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 module = calloc(1, sizeof *module);
5361 if (!module) {
5362 LOGMEM;
5363 goto error;
5364 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 module->ctx = ctx;
5367 module->name = lydict_insert(ctx, value, strlen(value));
5368 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005369 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005370
Michal Vasko9f258e42016-02-11 11:36:27 +01005371 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005372 if (read_sub_module(module, NULL, yin, unres)) {
5373 goto error;
5374 }
5375
5376 /* resolve rest of unres items */
5377 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005378 goto error;
5379 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005381 /* add to the context's list of modules */
5382 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005383 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005384 if (!newlist) {
5385 LOGMEM;
5386 goto error;
5387 }
5388 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5389 newlist[i] = NULL;
5390 }
5391 ctx->models.size *= 2;
5392 ctx->models.list = newlist;
5393 }
5394 for (i = 0; ctx->models.list[i]; i++) {
5395 /* check name (name/revision) and namespace uniqueness */
5396 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005397 if (ctx->models.list[i]->rev_size == module->rev_size) {
5398 /* both have the same number of revisions */
5399 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5400 /* both have the same revision -> we already have the same module */
5401 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005402 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005403
Michal Vasko9f258e42016-02-11 11:36:27 +01005404 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005405 module = ctx->models.list[i];
5406 if (implement && !module->implemented) {
5407 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005408 }
Radek Krejcic071c542016-01-27 14:57:51 +01005409
5410 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005411 }
5412 }
Radek Krejcif647e612015-07-30 11:36:07 +02005413 /* else (both elses) keep searching, for now the caller is just adding
5414 * another revision of an already present schema
5415 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005416 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005417 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005418 ctx->models.list[i]->name, module->name, module->ns);
5419 goto error;
5420 }
5421 }
5422 ctx->models.list[i] = module;
5423 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005424 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005425
Radek Krejcic071c542016-01-27 14:57:51 +01005426success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005428 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005429 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005430
Michal Vasko9f258e42016-02-11 11:36:27 +01005431 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005433 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005434
5435error:
Michal Vasko9f258e42016-02-11 11:36:27 +01005436 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
5437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005438 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005439 unres_schema_free(module, &unres);
Radek Krejcic071c542016-01-27 14:57:51 +01005440 lyxml_free(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005441
Michal Vasko9f258e42016-02-11 11:36:27 +01005442 /* warn about applied deviations */
5443 for (i = 0; i < module->deviation_size; ++i) {
5444 if (module->deviation[i].target) {
5445 LOGERR(ly_errno, "Module parsing failed, but successfully deviated %smodule \"%s\".",
5446 (module->deviation[i].target->module->type ? "sub" : ""),
5447 module->deviation[i].target->module->name);
5448 }
5449 }
5450
5451 /* remove applied augments */
5452 for (i = 0; i < module->augment_size; ++i) {
5453 if (module->augment[i].target) {
5454 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5455 if (elem->parent == (struct lys_node *)&module->augment[i]) {
5456 lys_node_free(elem, NULL);
5457 }
5458 }
5459 }
5460 }
5461
5462 lys_free(module, NULL, 1);
5463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005464 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005465}