blob: 2c7917bf9f3be18fe46be9c279666a3bd16a3562 [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 Vasko1e62a092015-12-01 12:27:20 +01001230 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, (const struct lys_node **)&dev->target);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001231 if (rc) {
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 Vasko1e62a092015-12-01 12:27:20 +01001408 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE,
1409 (const struct lys_node **)&node);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001410 if (rc) {
1411 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1412 goto error;
1413 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001414 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001415 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001416 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1417 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 goto error;
1419 }
1420 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001421 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001422 if (!choice->dflt) {
1423 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001424 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001425 goto error;
1426 }
1427 }
Radek Krejci76512572015-08-04 09:47:08 +02001428 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001429 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001430
1431 if (d->mod == LY_DEVIATE_ADD) {
1432 /* check that there is no current value */
1433 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001434 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1435 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001436 goto error;
1437 }
1438 }
1439
1440 if (d->mod == LY_DEVIATE_DEL) {
1441 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001442 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1443 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001444 goto error;
1445 }
1446 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001447 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001448 leaf->dflt = NULL;
1449 } else { /* add (already checked) and replace */
1450 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001451 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001452
1453 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001454 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001455 }
1456 } else {
1457 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001458 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1459 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001460 goto error;
1461 }
1462 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001463 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001464 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001465 goto error;
1466 }
1467
1468 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001469 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001470 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1471 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001472 goto error;
1473 }
1474
1475 GETVAL(value, child, "value");
1476 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001477 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001478 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001479 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001480 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001481 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001482 goto error;
1483 }
1484
1485 if (d->mod == LY_DEVIATE_ADD) {
1486 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001487 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001488 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1489 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001490 goto error;
1491 }
1492 }
1493
1494 if (d->mod == LY_DEVIATE_DEL) {
1495 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001496 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001497 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1498 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001499 goto error;
1500 }
1501 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001502 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001503 } else { /* add (already checked) and replace */
1504 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001505 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001506
1507 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001508 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001509 }
1510 } else if (!strcmp(child->name, "min-elements")) {
1511 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001512 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 goto error;
1514 }
1515 f_min = 1;
1516
1517 if (deviate_minmax(dev->target, child, d, 0)) {
1518 goto error;
1519 }
1520 } else if (!strcmp(child->name, "max-elements")) {
1521 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001522 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001523 goto error;
1524 }
1525
1526 if (deviate_minmax(dev->target, child, d, 1)) {
1527 goto error;
1528 }
1529 } else if (!strcmp(child->name, "must")) {
1530 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001531 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 continue;
1533 } else if (!strcmp(child->name, "type")) {
1534 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001535 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001536 goto error;
1537 }
1538
1539 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001540 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001541 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001542 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001543 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001545 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1546 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001547 goto error;
1548 }
1549
1550 if (d->mod == LY_DEVIATE_ADD) {
1551 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001552 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1553 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 goto error;
1555 } else if (d->mod == LY_DEVIATE_DEL) {
1556 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001557 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1558 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001559 goto error;
1560 }
1561
1562 /* replace */
1563 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001564 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001565
1566 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001567 /* HACK for unres */
1568 t->der = (struct lys_tpdf *)child;
1569 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev->target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001570 goto error;
1571 }
1572 d->type = t;
1573 } else if (!strcmp(child->name, "unique")) {
1574 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001575 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001576 continue;
1577 } else if (!strcmp(child->name, "units")) {
1578 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001579 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001580 goto error;
1581 }
1582
1583 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001584 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001585 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001586 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001587 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001588 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001589 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1590 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001591 goto error;
1592 }
1593
1594 /* get units value */
1595 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001596 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001597
1598 /* apply to target */
1599 if (d->mod == LY_DEVIATE_ADD) {
1600 /* check that there is no current value */
1601 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001602 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1603 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001604 goto error;
1605 }
1606 }
1607
1608 if (d->mod == LY_DEVIATE_DEL) {
1609 /* check values */
1610 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001611 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1612 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001613 goto error;
1614 }
1615 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001616 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001617 } else { /* add (already checked) and replace */
1618 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001619 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001620
1621 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001622 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001623 }
1624 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001625 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001626 goto error;
1627 }
1628
Michal Vasko88c29542015-11-27 14:57:53 +01001629 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001630 }
1631
1632 if (c_must) {
1633 /* check target node type */
1634 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001635 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001636 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1637 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 break;
Radek Krejci76512572015-08-04 09:47:08 +02001639 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001640 trg_must = &((struct lys_node_container *)dev->target)->must;
1641 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 break;
Radek Krejci76512572015-08-04 09:47:08 +02001643 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001644 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1645 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 break;
Radek Krejci76512572015-08-04 09:47:08 +02001647 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001648 trg_must = &((struct lys_node_list *)dev->target)->must;
1649 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 break;
Radek Krejci76512572015-08-04 09:47:08 +02001651 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001652 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1653 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001654 break;
1655 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001656 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1657 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001658 goto error;
1659 }
1660
1661 if (d->mod == LY_DEVIATE_RPL) {
1662 /* remove target's musts and allocate new array for it */
1663 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001664 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1665 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 goto error;
1667 }
1668
1669 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001670 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 }
1672 free(*trg_must);
1673 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1674 d->must_size = c_must;
1675 *trg_must_size = 0;
1676 } else if (d->mod == LY_DEVIATE_ADD) {
1677 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001678 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001679 if (!d->must) {
1680 LOGMEM;
1681 goto error;
1682 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001683 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001684 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001685 d->must_size = c_must;
1686 } else { /* LY_DEVIATE_DEL */
1687 d->must = calloc(c_must, sizeof *d->must);
1688 }
Michal Vasko253035f2015-12-17 16:58:13 +01001689 if (!d->must) {
1690 LOGMEM;
1691 goto error;
1692 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001693 }
1694 if (c_uniq) {
1695 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001696 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001697 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1698 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001699 goto error;
1700 }
1701
Radek Krejcib8048692015-08-05 13:36:34 +02001702 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001703 if (d->mod == LY_DEVIATE_RPL) {
1704 /* remove target's unique and allocate new array for it */
1705 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001706 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1707 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001708 goto error;
1709 }
1710
1711 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001712 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001713 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001714 }
1715 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 }
1717 free(list->unique);
1718 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1719 d->unique_size = c_uniq;
1720 list->unique_size = 0;
1721 } else if (d->mod == LY_DEVIATE_ADD) {
1722 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001723 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001724 list->unique = d->unique;
1725 d->unique = &list->unique[list->unique_size];
1726 d->unique_size = c_uniq;
1727 } else { /* LY_DEVIATE_DEL */
1728 d->unique = calloc(c_uniq, sizeof *d->unique);
1729 }
Michal Vasko253035f2015-12-17 16:58:13 +01001730 if (!d->unique) {
1731 LOGMEM;
1732 goto error;
1733 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001734 }
1735
1736 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001737 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 if (!strcmp(child->name, "must")) {
1739 if (d->mod == LY_DEVIATE_DEL) {
1740 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1741 goto error;
1742 }
1743
1744 /* find must to delete, we are ok with just matching conditions */
1745 for (i = 0; i < *trg_must_size; i++) {
1746 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1747 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001748 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001749 /* ... and maintain the array */
1750 (*trg_must_size)--;
1751 if (i != *trg_must_size) {
1752 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1753 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1754 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1755 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1756 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1757 }
1758 if (!(*trg_must_size)) {
1759 free(*trg_must);
1760 *trg_must = NULL;
1761 } else {
1762 (*trg_must)[*trg_must_size].expr = NULL;
1763 (*trg_must)[*trg_must_size].dsc = NULL;
1764 (*trg_must)[*trg_must_size].ref = NULL;
1765 (*trg_must)[*trg_must_size].eapptag = NULL;
1766 (*trg_must)[*trg_must_size].emsg = NULL;
1767 }
1768
1769 i = -1; /* set match flag */
1770 break;
1771 }
1772 }
1773 d->must_size++;
1774 if (i != -1) {
1775 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001776 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1777 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001778 goto error;
1779 }
1780 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001781 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1782 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001783 goto error;
1784 }
1785 (*trg_must_size)++;
1786 }
1787 } else if (!strcmp(child->name, "unique")) {
1788 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci581ce772015-11-10 17:22:40 +01001789 if (fill_yin_unique(module, dev->target, child, &d->unique[d->unique_size], NULL)) {
1790 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 goto error;
1792 }
1793
1794 /* find unique structures to delete */
1795 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001796 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001797 continue;
1798 }
1799
Radek Krejci581ce772015-11-10 17:22:40 +01001800 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1801 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001802 break;
1803 }
1804 }
1805
Radek Krejci581ce772015-11-10 17:22:40 +01001806 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001808 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001809 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001810 }
1811 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001812 /* ... and maintain the array */
1813 list->unique_size--;
1814 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001815 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1816 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001817 }
1818
1819 if (!list->unique_size) {
1820 free(list->unique);
1821 list->unique = NULL;
1822 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001823 list->unique[list->unique_size].expr_size = 0;
1824 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 }
1826
1827 i = -1; /* set match flag */
1828 break;
1829 }
1830 }
1831
1832 d->unique_size++;
1833 if (i != -1) {
1834 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001835 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1836 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001837 goto error;
1838 }
1839 } else { /* replace or add */
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001840 i = fill_yin_unique(module, dev->target, child, &list->unique[list->unique_size], NULL);
1841 list->unique_size++;
1842 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001843 goto error;
1844 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001845 }
1846 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001847 }
Radek Krejci5b917642015-07-02 09:03:13 +02001848
1849 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001850 }
1851
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 return EXIT_SUCCESS;
1853
1854error:
1855
Radek Krejcieb00f512015-07-01 16:44:58 +02001856 return EXIT_FAILURE;
1857}
1858
Michal Vasko0d343d12015-08-24 14:57:36 +02001859/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001860static int
Radek Krejcib8048692015-08-05 13:36:34 +02001861fill_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 +02001862 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001863{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001865 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001866 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001867 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001868
Michal Vasko591e0b22015-08-13 13:53:43 +02001869 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001870 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001871 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001872 if (!aug->target_name) {
1873 goto error;
1874 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001876
Michal Vasko1d87a922015-08-21 12:57:16 +02001877 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001878 goto error;
1879 }
1880
1881 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001882 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1883 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001884 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001885 continue;
1886 }
1887
Radek Krejci3cf9e222015-06-18 11:37:50 +02001888 if (!strcmp(child->name, "if-feature")) {
1889 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001890 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001891 } else if (!strcmp(child->name, "when")) {
1892 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001893 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001894 goto error;
1895 }
1896
1897 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001898 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001899 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001900 goto error;
1901 }
Michal Vaskofcdac172015-10-07 09:35:05 +02001902 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001903 goto error;
1904 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001905 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001906 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001907
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001908 /* check allowed data sub-statements */
1909 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001910 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001911 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001913 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001914 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001915 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001916 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001917 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001918 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001919 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001920 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001921 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001923 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001925 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001926 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001927 goto error;
1928 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001929
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001931 goto error;
1932 }
1933
1934 /* check for mandatory nodes - if the target node is in another module
1935 * the added nodes cannot be mandatory
1936 */
Radek Krejcic6556022016-01-27 15:16:45 +01001937 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001938 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001939 goto error;
1940 }
1941
Radek Krejci1d82ef62015-08-07 14:44:40 +02001942 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001943 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001944 }
1945
1946 if (c) {
1947 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001948 if (!aug->features) {
1949 LOGMEM;
1950 goto error;
1951 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001952 }
1953
1954 LY_TREE_FOR_SAFE(yin->child, next, child) {
1955 if (!strcmp(child->name, "if-feature")) {
1956 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001957 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001958 goto error;
1959 }
Radek Krejcicf509982015-12-15 09:22:44 +01001960 /* hack - store pointer to the parent node for later status check */
1961 aug->features[aug->features_size] = (struct lys_feature *)aug;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001962 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001963 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001964 aug->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001965 lydict_remove(module->ctx, value);
1966 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001967 goto error;
1968 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001969 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001970 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001971 }
1972
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001973 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02001974 * connected to the tree and adjusted (if possible right now).
1975 * However, if this is augment in a uses, it gets resolved
1976 * when the uses does and cannot be resolved now for sure
1977 * (the grouping was not yet copied into uses).
1978 */
1979 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02001980 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02001981 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
1982 goto error;
1983 }
Michal Vasko49291b32015-08-06 09:49:41 +02001984 }
Radek Krejci106efc02015-06-10 14:36:27 +02001985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02001987
1988error:
1989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02001991}
1992
Michal Vasko0d343d12015-08-24 14:57:36 +02001993/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001994static int
Michal Vasko0d204592015-10-07 09:50:04 +02001995fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02001996{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 struct lyxml_elem *sub, *next;
1998 const char *value;
1999 char *endptr;
2000 int f_mand = 0, f_min = 0, f_max = 0;
2001 int c_must = 0;
2002 int r;
2003 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002004
Radek Krejci76512572015-08-04 09:47:08 +02002005 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002006 goto error;
2007 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002008
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002010 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002011 if (!rfn->target_name) {
2012 goto error;
2013 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002015 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002016 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2017 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002018 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002019 continue;
2020 }
2021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002022 /* limited applicability */
2023 if (!strcmp(sub->name, "default")) {
2024 /* leaf or choice */
2025 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002026 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 goto error;
2028 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 /* check possibility of statements combination */
2031 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002032 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002034 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002035 goto error;
2036 }
2037 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002038 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 GETVAL(value, sub, "value");
2042 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2043 } else if (!strcmp(sub->name, "mandatory")) {
2044 /* leaf, choice or anyxml */
2045 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002046 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 goto error;
2048 }
2049 /* just checking the flags in leaf is not sufficient, we would allow
2050 * multiple mandatory statements with the "false" value
2051 */
2052 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054 /* check possibility of statements combination */
2055 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002056 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002057 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002058 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 goto error;
2060 }
2061 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002062 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 GETVAL(value, sub, "value");
2066 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002067 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002069 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002071 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 goto error;
2073 }
2074 } else if (!strcmp(sub->name, "min-elements")) {
2075 /* list or leaf-list */
2076 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002077 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 goto error;
2079 }
2080 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 /* check possibility of statements combination */
2083 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002084 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002086 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 goto error;
2088 }
2089 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002090 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 GETVAL(value, sub, "value");
2094 while (isspace(value[0])) {
2095 value++;
2096 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 /* convert it to uint32_t */
2099 errno = 0;
2100 endptr = NULL;
2101 val = strtoul(value, &endptr, 10);
2102 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002103 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 goto error;
2105 }
2106 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 /* magic - bit 3 in flags means min set */
2109 rfn->flags |= 0x04;
2110 } else if (!strcmp(sub->name, "max-elements")) {
2111 /* list or leaf-list */
2112 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002113 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 goto error;
2115 }
2116 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 /* check possibility of statements combination */
2119 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002120 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002122 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 goto error;
2124 }
2125 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002126 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 GETVAL(value, sub, "value");
2130 while (isspace(value[0])) {
2131 value++;
2132 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 /* convert it to uint32_t */
2135 errno = 0;
2136 endptr = NULL;
2137 val = strtoul(value, &endptr, 10);
2138 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002139 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 goto error;
2141 }
2142 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 /* magic - bit 4 in flags means min set */
2145 rfn->flags |= 0x08;
2146 } else if (!strcmp(sub->name, "presence")) {
2147 /* container */
2148 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002149 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 goto error;
2151 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 /* check possibility of statements combination */
2154 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002155 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002157 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 goto error;
2159 }
2160 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002161 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 GETVAL(value, sub, "value");
2165 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2166 } else if (!strcmp(sub->name, "must")) {
2167 /* leaf-list, list, container or anyxml */
2168 /* check possibility of statements combination */
2169 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002170 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002172 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 goto error;
2174 }
2175 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002176 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002180 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002183 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 goto error;
2185 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002186
Michal Vasko345da0a2015-12-02 10:35:55 +01002187 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 /* process nodes with cardinality of 0..n */
2191 if (c_must) {
2192 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002193 if (!rfn->must) {
2194 LOGMEM;
2195 goto error;
2196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
Radek Krejci73adb602015-07-02 18:07:40 +02002198 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002199 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2200 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002201 if (r) {
2202 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 }
Michal Vasko0d204592015-10-07 09:50:04 +02002204 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002205 goto error;
2206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002210
2211error:
2212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002214}
2215
Michal Vasko0d343d12015-08-24 14:57:36 +02002216/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217static int
Radek Krejcib8048692015-08-05 13:36:34 +02002218fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002219{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 struct lyxml_elem *child;
2221 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002222 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002225 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2226 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002227 continue;
2228 }
2229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 if (!strcmp(child->name, "prefix")) {
2231 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002232 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 goto error;
2234 }
2235 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2236 } else if (!strcmp(child->name, "revision-date")) {
2237 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002238 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 goto error;
2240 }
2241 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002242 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 goto error;
2244 }
2245 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2246 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002247 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 goto error;
2249 }
2250 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 /* check mandatory information */
2253 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002254 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 goto error;
2256 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002259
2260 /* check for circular import, store it if passed */
2261 if (!module->ctx->models.parsing) {
2262 count = 0;
2263 } else {
2264 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2265 if (value == module->ctx->models.parsing[count]) {
2266 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2267 goto error;
2268 }
2269 }
2270 }
2271 ++count;
2272 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002273 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2274 if (!module->ctx->models.parsing) {
2275 LOGMEM;
2276 goto error;
2277 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002278 module->ctx->models.parsing[count - 1] = value;
2279 module->ctx->models.parsing[count] = NULL;
2280
2281 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002282 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 +02002283 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002284 /* whether to use a user callback is decided in the function */
2285 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 +02002286 }
2287
2288 /* remove the new module name now that its parsing is finished (even if failed) */
2289 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2290 LOGINT;
2291 }
2292 --count;
2293 if (count) {
2294 module->ctx->models.parsing[count] = NULL;
2295 } else {
2296 free(module->ctx->models.parsing);
2297 module->ctx->models.parsing = NULL;
2298 }
2299
2300 /* check the result */
2301 if (!imp->module) {
2302 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2303 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2304 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002308
2309error:
2310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002312}
2313
Michal Vasko0d343d12015-08-24 14:57:36 +02002314/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315static int
Radek Krejcic071c542016-01-27 14:57:51 +01002316fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, 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 Vasko1b882eb2015-10-22 11:43:14 +02002323 int count;
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
2348 /* check for circular include, store it if passed */
2349 if (!module->ctx->models.parsing) {
2350 count = 0;
2351 } else {
2352 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2353 if (value == module->ctx->models.parsing[count]) {
2354 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2355 goto error;
2356 }
2357 }
2358 }
2359 ++count;
2360 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002361 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2362 if (!module->ctx->models.parsing) {
2363 LOGMEM;
2364 goto error;
2365 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002366 module->ctx->models.parsing[count - 1] = value;
2367 module->ctx->models.parsing[count] = NULL;
2368
2369 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002370 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002372 if (module->ctx->module_clb) {
2373 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2374 &format, &module_data_free);
2375 if (module_data) {
Radek Krejcic071c542016-01-27 14:57:51 +01002376 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002377 if (module_data_free) {
2378 module_data_free(module_data);
2379 } else {
2380 free(module_data);
2381 }
2382 } else {
2383 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2384 }
2385 } else {
2386 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
Radek Krejcic071c542016-01-27 14:57:51 +01002387 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002388 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002389 }
2390
2391 /* remove the new submodule name now that its parsing is finished (even if failed) */
2392 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2393 LOGINT;
2394 }
2395 --count;
2396 if (count) {
2397 module->ctx->models.parsing[count] = NULL;
2398 } else {
2399 free(module->ctx->models.parsing);
2400 module->ctx->models.parsing = NULL;
2401 }
2402
2403 /* check the result */
2404 if (!inc->submodule) {
2405 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2406 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2407 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002411
2412error:
2413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002414 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002415}
2416
Michal Vasko0d343d12015-08-24 14:57:36 +02002417/* logs directly
2418 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002419 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002420 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002421 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002422 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423static int
Radek Krejcib8048692015-08-05 13:36:34 +02002424read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002425 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002426{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427 const char *value;
2428 struct lyxml_elem *sub, *next;
2429 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002432 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 if (opt & OPT_IDENT) {
2436 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002437 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 goto error;
2439 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002440 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002442
Radek Krejci6764bb32015-07-03 15:16:04 +02002443 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002444 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002445 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002446 }
2447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 /* process local parameters */
2449 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002450 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002451 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002452 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002453 continue;
2454 }
2455 if (strcmp(sub->ns->value, LY_NSYIN)) {
2456 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002457 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002458 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002460 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002461 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002462 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002463 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002464 goto error;
2465 }
2466 }
2467
2468 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002469 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002470 continue;
2471 }
2472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002474 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002475 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 goto error;
2477 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002478 node->dsc = read_yin_subnode(ctx, sub, "text");
2479 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002480 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 }
2482 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002483 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002484 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 goto error;
2486 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002487 node->ref = read_yin_subnode(ctx, sub, "text");
2488 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002489 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002490 }
2491 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002492 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002493 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 goto error;
2495 }
2496 GETVAL(value, sub, "value");
2497 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002498 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002500 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002502 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002504 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002505 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002506 }
2507 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002508 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002509 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 goto error;
2511 }
2512 GETVAL(value, sub, "value");
2513 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002514 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002515 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002516 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002517 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002518 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002519 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 }
2521 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002522 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002523 continue;
2524 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002525 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002527
Radek Krejci1d82ef62015-08-07 14:44:40 +02002528 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 /* get config flag from parent */
2530 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002531 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002532 } else {
2533 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002534 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 }
2536 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002539
2540error:
2541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002542 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002543}
2544
Michal Vasko0d343d12015-08-24 14:57:36 +02002545/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002546static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002547read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002548{
Radek Krejci76512572015-08-04 09:47:08 +02002549 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002550 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002551 const char *value;
2552
2553 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002554 if (!retval) {
2555 LOGMEM;
2556 return NULL;
2557 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002558
2559 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002560 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002561 if (!retval->cond) {
2562 goto error;
2563 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002564
Radek Krejci73adb602015-07-02 18:07:40 +02002565 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002566 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2567 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002568 continue;
2569 }
2570
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002571 if (!strcmp(child->name, "description")) {
2572 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002573 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002574 goto error;
2575 }
2576 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2577 if (!retval->dsc) {
2578 goto error;
2579 }
2580 } else if (!strcmp(child->name, "reference")) {
2581 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002582 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002583 goto error;
2584 }
2585 retval->ref = read_yin_subnode(module->ctx, child, "text");
2586 if (!retval->ref) {
2587 goto error;
2588 }
2589 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002590 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002591 goto error;
2592 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002593 }
2594
2595 return retval;
2596
2597error:
2598
Michal Vasko0308dd62015-10-07 09:14:40 +02002599 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002600 return NULL;
2601}
2602
Michal Vasko0d343d12015-08-24 14:57:36 +02002603/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002604static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002605read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2606 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002607{
Michal Vasko29fc0182015-08-24 15:02:39 +02002608 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002609 struct lys_node_case *cs;
2610 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002611 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002612 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002613
Radek Krejcie867c852015-08-27 09:52:34 +02002614 /* init */
2615 memset(&root, 0, sizeof root);
2616
Radek Krejci1d82ef62015-08-07 14:44:40 +02002617 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002618 if (!cs) {
2619 LOGMEM;
2620 return NULL;
2621 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002622 cs->nodetype = LYS_CASE;
2623 cs->prev = (struct lys_node *)cs;
2624 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002625
Radek Krejci6a113852015-07-03 16:04:20 +02002626 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 goto error;
2628 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002629
Radek Krejcia9544502015-08-14 08:24:29 +02002630 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2631
Michal Vasko3a0043f2015-08-12 12:11:30 +02002632 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002633 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002634 goto error;
2635 }
2636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002637 /* process choice's specific children */
2638 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002639 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2640 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002641 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002642 continue;
2643 }
2644
Michal Vasko29fc0182015-08-24 15:02:39 +02002645 if (!strcmp(sub->name, "container") ||
2646 !strcmp(sub->name, "leaf-list") ||
2647 !strcmp(sub->name, "leaf") ||
2648 !strcmp(sub->name, "list") ||
2649 !strcmp(sub->name, "uses") ||
2650 !strcmp(sub->name, "choice") ||
2651 !strcmp(sub->name, "anyxml")) {
2652
Michal Vaskof3930de2015-10-22 12:03:59 +02002653 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002654 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002655 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002656 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002657 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002658 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002659 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002660 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002661 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002662 goto error;
2663 }
2664
Radek Krejci1d82ef62015-08-07 14:44:40 +02002665 cs->when = read_yin_when(module, sub);
2666 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002667 goto error;
2668 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002669 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002670 goto error;
2671 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002672
Michal Vasko345da0a2015-12-02 10:35:55 +01002673 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002675 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002676 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002677 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002679
Radek Krejci3cf9e222015-06-18 11:37:50 +02002680 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002681 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002682 if (!cs->features) {
2683 LOGMEM;
2684 goto error;
2685 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002686 }
Radek Krejci73adb602015-07-02 18:07:40 +02002687 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002688 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002689 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002690 goto error;
2691 }
Radek Krejcicf509982015-12-15 09:22:44 +01002692 /* hack - store pointer to the parent node for later status check */
2693 cs->features[cs->features_size] = (struct lys_feature *)cs;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002694 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002695 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002696 cs->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002697 lydict_remove(module->ctx, value);
2698 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002699 goto error;
2700 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002701 }
Radek Krejcib388c152015-06-04 17:03:03 +02002702
Michal Vasko29fc0182015-08-24 15:02:39 +02002703 /* last part - process data nodes */
2704 LY_TREE_FOR_SAFE(root.child, next, sub) {
2705 if (!strcmp(sub->name, "container")) {
2706 node = read_yin_container(module, retval, sub, resolve, unres);
2707 } else if (!strcmp(sub->name, "leaf-list")) {
2708 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2709 } else if (!strcmp(sub->name, "leaf")) {
2710 node = read_yin_leaf(module, retval, sub, resolve, unres);
2711 } else if (!strcmp(sub->name, "list")) {
2712 node = read_yin_list(module, retval, sub, resolve, unres);
2713 } else if (!strcmp(sub->name, "choice")) {
2714 node = read_yin_choice(module, retval, sub, resolve, unres);
2715 } else if (!strcmp(sub->name, "uses")) {
2716 node = read_yin_uses(module, retval, sub, resolve, unres);
2717 } else if (!strcmp(sub->name, "anyxml")) {
2718 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2719 }
2720 if (!node) {
2721 goto error;
2722 }
2723
Michal Vasko345da0a2015-12-02 10:35:55 +01002724 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002725 }
2726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002728
2729error:
2730
Michal Vasko29fc0182015-08-24 15:02:39 +02002731 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002732 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002733 }
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002734 lys_node_free(retval, NULL);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002737}
2738
Michal Vasko0d343d12015-08-24 14:57:36 +02002739/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002740static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002741read_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 +02002742{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 struct lyxml_elem *sub, *next;
2744 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002745 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002746 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002747 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002748 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002750 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002751 if (!choice) {
2752 LOGMEM;
2753 return NULL;
2754 }
Radek Krejci76512572015-08-04 09:47:08 +02002755 choice->nodetype = LYS_CHOICE;
2756 choice->prev = (struct lys_node *)choice;
2757 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002758
Michal Vaskoe0c59842015-09-24 13:52:20 +02002759 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2760 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 goto error;
2762 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002763
Radek Krejcia9544502015-08-14 08:24:29 +02002764 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2765
Michal Vasko3a0043f2015-08-12 12:11:30 +02002766 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002767 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002768 goto error;
2769 }
2770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 /* process choice's specific children */
2772 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002773 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2774 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002775 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002776 continue;
2777 }
2778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002780 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 goto error;
2782 }
2783 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002784 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 goto error;
2786 }
2787 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002788 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002789 goto error;
2790 }
2791 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002792 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002793 goto error;
2794 }
2795 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002796 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002797 goto error;
2798 }
2799 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002800 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 goto error;
2802 }
2803 } else if (!strcmp(sub->name, "default")) {
2804 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002805 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002806 goto error;
2807 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002808 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 } else if (!strcmp(sub->name, "mandatory")) {
2810 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002811 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 goto error;
2813 }
2814 /* just checking the flags in leaf is not sufficient, we would allow
2815 * multiple mandatory statements with the "false" value
2816 */
2817 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 GETVAL(value, sub, "value");
2820 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002821 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002822 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002823 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002824 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002825 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 goto error;
2827 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002828 } else if (!strcmp(sub->name, "when")) {
2829 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002830 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002831 goto error;
2832 }
2833
2834 choice->when = read_yin_when(module, sub);
2835 if (!choice->when) {
2836 goto error;
2837 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002838 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002839 goto error;
2840 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002841 } else if (!strcmp(sub->name, "if-feature")) {
2842 c_ftrs++;
2843
Michal Vasko345da0a2015-12-02 10:35:55 +01002844 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002845 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002846 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002847 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002850
Radek Krejci1d82ef62015-08-07 14:44:40 +02002851 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002852 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002854
Radek Krejci3cf9e222015-06-18 11:37:50 +02002855 if (c_ftrs) {
2856 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002857 if (!choice->features) {
2858 LOGMEM;
2859 goto error;
2860 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002861 }
2862
Radek Krejci73adb602015-07-02 18:07:40 +02002863 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002864 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002865 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002866 goto error;
2867 }
Radek Krejcicf509982015-12-15 09:22:44 +01002868 /* hack - store pointer to the parent node for later status check */
2869 choice->features[choice->features_size] = (struct lys_feature *)choice;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002870 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002871 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002872 choice->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002873 lydict_remove(module->ctx, value);
2874 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002875 goto error;
2876 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002877 }
2878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002879 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002880 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002881 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002882 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2883 goto error;
2884 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 /* link default with the case */
2887 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002888 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002889 goto error;
2890 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002891 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002894
2895error:
2896
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002897 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002900}
2901
Michal Vasko0d343d12015-08-24 14:57:36 +02002902/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002903static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002904read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002905 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002906{
Radek Krejci76512572015-08-04 09:47:08 +02002907 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002908 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002909 struct lyxml_elem *sub, *next;
2910 const char *value;
2911 int r;
2912 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002913 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002916 if (!anyxml) {
2917 LOGMEM;
2918 return NULL;
2919 }
Radek Krejci76512572015-08-04 09:47:08 +02002920 anyxml->nodetype = LYS_ANYXML;
2921 anyxml->prev = (struct lys_node *)anyxml;
2922 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002923
Michal Vaskoe0c59842015-09-24 13:52:20 +02002924 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2925 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 goto error;
2927 }
Radek Krejci863c2852015-06-03 15:47:11 +02002928
Radek Krejcia9544502015-08-14 08:24:29 +02002929 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002930
Radek Krejcic071c542016-01-27 14:57:51 +01002931 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002932 goto error;
2933 }
2934
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002936 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2937 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002938 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002939 continue;
2940 }
2941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 if (!strcmp(sub->name, "mandatory")) {
2943 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002944 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002945 goto error;
2946 }
2947 /* just checking the flags in leaf is not sufficient, we would allow
2948 * multiple mandatory statements with the "false" value
2949 */
2950 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 GETVAL(value, sub, "value");
2953 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002954 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002955 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002956 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002957 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002958 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 goto error;
2960 }
2961 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002962 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002963 } else if (!strcmp(sub->name, "when")) {
2964 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002965 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002966 goto error;
2967 }
2968
2969 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002970 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002971 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002972 goto error;
2973 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002974 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002975 goto error;
2976 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002977 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 } else if (!strcmp(sub->name, "must")) {
2979 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002980 } else if (!strcmp(sub->name, "if-feature")) {
2981 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002984 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002986 }
2987 }
Radek Krejci863c2852015-06-03 15:47:11 +02002988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002989 /* middle part - process nodes with cardinality of 0..n */
2990 if (c_must) {
2991 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002992 if (!anyxml->must) {
2993 LOGMEM;
2994 goto error;
2995 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002997 if (c_ftrs) {
2998 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002999 if (!anyxml->features) {
3000 LOGMEM;
3001 goto error;
3002 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003003 }
Radek Krejci863c2852015-06-03 15:47:11 +02003004
Radek Krejci73adb602015-07-02 18:07:40 +02003005 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003007 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3008 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 if (r) {
3010 goto error;
3011 }
Michal Vasko0d204592015-10-07 09:50:04 +02003012 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003013 goto error;
3014 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003015 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003016 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003017 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003018 goto error;
3019 }
Radek Krejcicf509982015-12-15 09:22:44 +01003020 /* hack - store pointer to the parent node for later status check */
3021 anyxml->features[anyxml->features_size] = (struct lys_feature *)anyxml;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003022 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003023 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003024 anyxml->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003025 lydict_remove(module->ctx, value);
3026 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003027 goto error;
3028 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 }
Radek Krejci863c2852015-06-03 15:47:11 +02003031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003033
3034error:
3035
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003036 lys_node_free(retval, NULL);
Radek Krejci863c2852015-06-03 15:47:11 +02003037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003039}
3040
Michal Vasko0d343d12015-08-24 14:57:36 +02003041/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003042static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003043read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003044 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003045{
Radek Krejci76512572015-08-04 09:47:08 +02003046 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003047 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 struct lyxml_elem *sub, *next;
3049 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003050 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003051 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003054 if (!leaf) {
3055 LOGMEM;
3056 return NULL;
3057 }
Radek Krejci76512572015-08-04 09:47:08 +02003058 leaf->nodetype = LYS_LEAF;
3059 leaf->prev = (struct lys_node *)leaf;
3060 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003061
Michal Vaskoe0c59842015-09-24 13:52:20 +02003062 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3063 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 goto error;
3065 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003066
Radek Krejcia9544502015-08-14 08:24:29 +02003067 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003068
Radek Krejcic071c542016-01-27 14:57:51 +01003069 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003070 goto error;
3071 }
3072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003074 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3075 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003076 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003077 continue;
3078 }
3079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003081 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003082 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 goto error;
3084 }
Michal Vasko88c29542015-11-27 14:57:53 +01003085 /* HACK for unres */
3086 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003087 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003088 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3089 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 goto error;
3091 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003092 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 } else if (!strcmp(sub->name, "default")) {
3094 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003095 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 goto error;
3097 }
3098 GETVAL(value, sub, "value");
3099 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003100 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 } else if (!strcmp(sub->name, "units")) {
3102 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003103 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 goto error;
3105 }
3106 GETVAL(value, sub, "name");
3107 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3108 } else if (!strcmp(sub->name, "mandatory")) {
3109 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003110 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003111 goto error;
3112 }
3113 /* just checking the flags in leaf is not sufficient, we would allow
3114 * multiple mandatory statements with the "false" value
3115 */
3116 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 GETVAL(value, sub, "value");
3119 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003120 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003121 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003122 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003123 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003124 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003127 } else if (!strcmp(sub->name, "when")) {
3128 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003129 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003130 goto error;
3131 }
3132
3133 leaf->when = read_yin_when(module, sub);
3134 if (!leaf->when) {
3135 goto error;
3136 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003137 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003138 goto error;
3139 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003141 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003142 c_must++;
3143 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003144 } else if (!strcmp(sub->name, "if-feature")) {
3145 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003146 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003148 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003149 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003150 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003151 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003152
Michal Vasko88c29542015-11-27 14:57:53 +01003153 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003154 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003157 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003158 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 goto error;
3160 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003161 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003162 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003163 goto error;
3164 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 /* middle part - process nodes with cardinality of 0..n */
3168 if (c_must) {
3169 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003170 if (!leaf->must) {
3171 LOGMEM;
3172 goto error;
3173 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003174 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003175 if (c_ftrs) {
3176 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003177 if (!leaf->features) {
3178 LOGMEM;
3179 goto error;
3180 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003181 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003182
Radek Krejci73adb602015-07-02 18:07:40 +02003183 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003184 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003185 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3186 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 if (r) {
3188 goto error;
3189 }
Michal Vasko0d204592015-10-07 09:50:04 +02003190 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003191 goto error;
3192 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003193 } else if (!strcmp(sub->name, "if-feature")) {
3194 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003195 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003196 goto error;
3197 }
Radek Krejcicf509982015-12-15 09:22:44 +01003198 /* hack - store pointer to the parent node for later status check */
3199 leaf->features[leaf->features_size] = (struct lys_feature *)leaf;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003200 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003201 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003202 leaf->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003203 lydict_remove(module->ctx, value);
3204 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003205 goto error;
3206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003211
3212error:
3213
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003214 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003217}
3218
Michal Vasko0d343d12015-08-24 14:57:36 +02003219/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003220static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003221read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003222 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003223{
Radek Krejci76512572015-08-04 09:47:08 +02003224 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003225 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003226 struct lyxml_elem *sub, *next;
3227 const char *value;
3228 char *endptr;
3229 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003230 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003231 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003235 if (!llist) {
3236 LOGMEM;
3237 return NULL;
3238 }
Radek Krejci76512572015-08-04 09:47:08 +02003239 llist->nodetype = LYS_LEAFLIST;
3240 llist->prev = (struct lys_node *)llist;
3241 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003242
Michal Vaskoe0c59842015-09-24 13:52:20 +02003243 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3244 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 goto error;
3246 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003247
Radek Krejcia9544502015-08-14 08:24:29 +02003248 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003249
Radek Krejcic071c542016-01-27 14:57:51 +01003250 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003251 goto error;
3252 }
3253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003255 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3256 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003257 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003258 continue;
3259 }
3260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003262 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003263 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 goto error;
3265 }
Michal Vasko88c29542015-11-27 14:57:53 +01003266 /* HACK for unres */
3267 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003268 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003269 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3270 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 goto error;
3272 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003273 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 } else if (!strcmp(sub->name, "units")) {
3275 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003276 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 goto error;
3278 }
3279 GETVAL(value, sub, "name");
3280 llist->units = lydict_insert(module->ctx, value, strlen(value));
3281 } else if (!strcmp(sub->name, "ordered-by")) {
3282 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003283 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 goto error;
3285 }
3286 /* just checking the flags in llist is not sufficient, we would
3287 * allow multiple ordered-by statements with the "system" value
3288 */
3289 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003290
Radek Krejci1574a8d2015-08-03 14:16:52 +02003291 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3293 * state data
3294 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003295 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 continue;
3297 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 GETVAL(value, sub, "value");
3300 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003301 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003303 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003305 } /* else system is the default value, so we can ignore it */
3306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 } else if (!strcmp(sub->name, "must")) {
3308 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003309 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003310 } else if (!strcmp(sub->name, "if-feature")) {
3311 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 } else if (!strcmp(sub->name, "min-elements")) {
3315 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003316 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 goto error;
3318 }
3319 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 GETVAL(value, sub, "value");
3322 while (isspace(value[0])) {
3323 value++;
3324 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 /* convert it to uint32_t */
3327 errno = 0;
3328 endptr = NULL;
3329 val = strtoul(value, &endptr, 10);
3330 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003331 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 goto error;
3333 }
3334 llist->min = (uint32_t) val;
3335 } else if (!strcmp(sub->name, "max-elements")) {
3336 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003337 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 goto error;
3339 }
3340 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 GETVAL(value, sub, "value");
3343 while (isspace(value[0])) {
3344 value++;
3345 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003347 /* convert it to uint32_t */
3348 errno = 0;
3349 endptr = NULL;
3350 val = strtoul(value, &endptr, 10);
3351 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003352 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 goto error;
3354 }
3355 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003356 } else if (!strcmp(sub->name, "when")) {
3357 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003358 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003359 goto error;
3360 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003361
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003362 llist->when = read_yin_when(module, sub);
3363 if (!llist->when) {
3364 goto error;
3365 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003366 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003367 goto error;
3368 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003370 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003372 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003373
Michal Vasko88c29542015-11-27 14:57:53 +01003374 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003377 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003378 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003379 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 goto error;
3381 }
3382 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003383 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 goto error;
3385 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 /* middle part - process nodes with cardinality of 0..n */
3388 if (c_must) {
3389 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003390 if (!llist->must) {
3391 LOGMEM;
3392 goto error;
3393 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003394 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003395 if (c_ftrs) {
3396 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003397 if (!llist->features) {
3398 LOGMEM;
3399 goto error;
3400 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003401 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003402
Radek Krejci73adb602015-07-02 18:07:40 +02003403 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003405 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3406 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 if (r) {
3408 goto error;
3409 }
Michal Vasko0d204592015-10-07 09:50:04 +02003410 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003411 goto error;
3412 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003413 } else if (!strcmp(sub->name, "if-feature")) {
3414 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003415 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003416 goto error;
3417 }
Radek Krejcicf509982015-12-15 09:22:44 +01003418 /* hack - store pointer to the parent node for later status check */
3419 llist->features[llist->features_size] = (struct lys_feature *)llist;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003420 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003421 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003422 llist->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003423 lydict_remove(module->ctx, value);
3424 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003425 goto error;
3426 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003431
3432error:
3433
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003434 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003437}
3438
Michal Vasko0d343d12015-08-24 14:57:36 +02003439/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003440static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003441read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3442 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003443{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003444 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003445 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003447 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003448 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003450 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 char *auxs;
3452 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 /* init */
3455 memset(&root, 0, sizeof root);
3456 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003458 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003459 if (!list) {
3460 LOGMEM;
3461 return NULL;
3462 }
Radek Krejci76512572015-08-04 09:47:08 +02003463 list->nodetype = LYS_LIST;
3464 list->prev = (struct lys_node *)list;
3465 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003466
Michal Vaskoe0c59842015-09-24 13:52:20 +02003467 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3468 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 goto error;
3470 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003471
Radek Krejcia9544502015-08-14 08:24:29 +02003472 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 /* process list's specific children */
3475 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003476 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3477 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003478 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003479 continue;
3480 }
3481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 /* data statements */
3483 if (!strcmp(sub->name, "container") ||
3484 !strcmp(sub->name, "leaf-list") ||
3485 !strcmp(sub->name, "leaf") ||
3486 !strcmp(sub->name, "list") ||
3487 !strcmp(sub->name, "choice") ||
3488 !strcmp(sub->name, "uses") ||
3489 !strcmp(sub->name, "grouping") ||
3490 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003491 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003492 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 /* array counters */
3495 } else if (!strcmp(sub->name, "key")) {
3496 /* check cardinality 0..1 */
3497 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003498 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 goto error;
3500 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 /* count the number of keys */
3503 GETVAL(value, sub, "value");
3504 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003505 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003506 while ((value = strpbrk(value, " \t\n"))) {
3507 list->keys_size++;
3508 while (isspace(*value)) {
3509 value++;
3510 }
3511 }
3512 list->keys_size++;
3513 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003514 if (!list->keys) {
3515 LOGMEM;
3516 goto error;
3517 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 } else if (!strcmp(sub->name, "unique")) {
3519 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003520 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003521 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003522 } else if (!strcmp(sub->name, "typedef")) {
3523 c_tpdf++;
3524 } else if (!strcmp(sub->name, "must")) {
3525 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003526 } else if (!strcmp(sub->name, "if-feature")) {
3527 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 /* optional stetments */
3530 } else if (!strcmp(sub->name, "ordered-by")) {
3531 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003532 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 goto error;
3534 }
3535 /* just checking the flags in llist is not sufficient, we would
3536 * allow multiple ordered-by statements with the "system" value
3537 */
3538 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003539
Radek Krejci1574a8d2015-08-03 14:16:52 +02003540 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3542 * state data
3543 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003544 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 continue;
3546 }
Radek Krejci345ad742015-06-03 11:04:18 +02003547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003548 GETVAL(value, sub, "value");
3549 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003550 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003551 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003552 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 goto error;
3554 }
3555 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003556 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 } else if (!strcmp(sub->name, "min-elements")) {
3558 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003559 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 goto error;
3561 }
3562 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 GETVAL(value, sub, "value");
3565 while (isspace(value[0])) {
3566 value++;
3567 }
Radek Krejci345ad742015-06-03 11:04:18 +02003568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003569 /* convert it to uint32_t */
3570 errno = 0;
3571 auxs = NULL;
3572 val = strtoul(value, &auxs, 10);
3573 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003574 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 goto error;
3576 }
3577 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003578 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 } else if (!strcmp(sub->name, "max-elements")) {
3580 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003581 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 goto error;
3583 }
3584 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 GETVAL(value, sub, "value");
3587 while (isspace(value[0])) {
3588 value++;
3589 }
Radek Krejci345ad742015-06-03 11:04:18 +02003590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003591 /* convert it to uint32_t */
3592 errno = 0;
3593 auxs = NULL;
3594 val = strtoul(value, &auxs, 10);
3595 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003596 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 goto error;
3598 }
3599 list->max = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003600 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003601 } else if (!strcmp(sub->name, "when")) {
3602 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003603 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003604 goto error;
3605 }
3606
3607 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003608 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003609 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003610 goto error;
3611 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003612 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003613 goto error;
3614 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003615 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003616 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003617 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003618 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 }
3620 }
Radek Krejci345ad742015-06-03 11:04:18 +02003621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003623 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003624 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 goto error;
3626 }
3627 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003628 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003629 goto error;
3630 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3633 if (c_tpdf) {
3634 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003635 if (!list->tpdf) {
3636 LOGMEM;
3637 goto error;
3638 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003640 if (c_must) {
3641 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003642 if (!list->must) {
3643 LOGMEM;
3644 goto error;
3645 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003646 }
3647 if (c_ftrs) {
3648 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003649 if (!list->features) {
3650 LOGMEM;
3651 goto error;
3652 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003653 }
Radek Krejci73adb602015-07-02 18:07:40 +02003654 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003656 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3657 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003658 if (r) {
3659 goto error;
3660 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003661 } else if (!strcmp(sub->name, "if-feature")) {
3662 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003663 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003664 goto error;
3665 }
Radek Krejcicf509982015-12-15 09:22:44 +01003666 /* hack - store pointer to the parent node for later status check */
3667 list->features[list->features_size] = (struct lys_feature *)list;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003668 r = unres_schema_add_str(module, unres, &list->features[list->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003669 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003670 list->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003671 lydict_remove(module->ctx, value);
3672 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003673 goto error;
3674 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003675 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003676 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3677 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003678 if (r) {
3679 goto error;
3680 }
Michal Vasko0d204592015-10-07 09:50:04 +02003681 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003682 goto error;
3683 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003684 }
3685 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003686
Radek Krejcic071c542016-01-27 14:57:51 +01003687 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003688 goto error;
3689 }
3690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 /* last part - process data nodes */
3692 LY_TREE_FOR_SAFE(root.child, next, sub) {
3693 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003694 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003696 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003698 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003700 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003702 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003704 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003706 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003708 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003709 } else {
3710 LOGINT;
3711 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003713 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 goto error;
3715 }
Radek Krejci73adb602015-07-02 18:07:40 +02003716
Michal Vasko345da0a2015-12-02 10:35:55 +01003717 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 if (!key_str) {
3721 /* config false list without a key */
3722 return retval;
3723 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003724 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003725 goto error;
3726 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 /* process unique statements */
3729 if (c_uniq) {
3730 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003731 if (!list->unique) {
3732 LOGMEM;
3733 goto error;
3734 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003735 }
3736 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003737 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3738 list->unique_size++;
3739 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003740 goto error;
3741 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003742
Michal Vasko345da0a2015-12-02 10:35:55 +01003743 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003747
3748error:
3749
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003750 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003752 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 }
3754 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003755 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003759}
3760
Michal Vasko0d343d12015-08-24 14:57:36 +02003761/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003762static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003763read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3764 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003765{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003767 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003768 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003769 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 const char *value;
3771 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003772 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 /* init */
3775 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003778 if (!cont) {
3779 LOGMEM;
3780 return NULL;
3781 }
Radek Krejci76512572015-08-04 09:47:08 +02003782 cont->nodetype = LYS_CONTAINER;
3783 cont->prev = (struct lys_node *)cont;
3784 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003785
Michal Vaskoe0c59842015-09-24 13:52:20 +02003786 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3787 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003788 goto error;
3789 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003790
Radek Krejcia9544502015-08-14 08:24:29 +02003791 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 /* process container's specific children */
3794 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003795 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003796 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003797 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003798 continue;
3799 }
3800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 if (!strcmp(sub->name, "presence")) {
3802 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003803 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 goto error;
3805 }
3806 GETVAL(value, sub, "value");
3807 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003808
Michal Vasko345da0a2015-12-02 10:35:55 +01003809 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003810 } else if (!strcmp(sub->name, "when")) {
3811 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003812 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003813 goto error;
3814 }
3815
3816 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003817 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003818 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003819 goto error;
3820 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003821 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003822 goto error;
3823 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003824 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 /* data statements */
3827 } else if (!strcmp(sub->name, "container") ||
3828 !strcmp(sub->name, "leaf-list") ||
3829 !strcmp(sub->name, "leaf") ||
3830 !strcmp(sub->name, "list") ||
3831 !strcmp(sub->name, "choice") ||
3832 !strcmp(sub->name, "uses") ||
3833 !strcmp(sub->name, "grouping") ||
3834 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003835 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003836 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 /* array counters */
3839 } else if (!strcmp(sub->name, "typedef")) {
3840 c_tpdf++;
3841 } else if (!strcmp(sub->name, "must")) {
3842 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003843 } else if (!strcmp(sub->name, "if-feature")) {
3844 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003846 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 }
3849 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3852 if (c_tpdf) {
3853 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003854 if (!cont->tpdf) {
3855 LOGMEM;
3856 goto error;
3857 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 }
3859 if (c_must) {
3860 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003861 if (!cont->must) {
3862 LOGMEM;
3863 goto error;
3864 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003866 if (c_ftrs) {
3867 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003868 if (!cont->features) {
3869 LOGMEM;
3870 goto error;
3871 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003872 }
Radek Krejci800af702015-06-02 13:46:01 +02003873
Radek Krejci73adb602015-07-02 18:07:40 +02003874 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003876 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3877 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 if (r) {
3879 goto error;
3880 }
3881 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003882 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3883 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 if (r) {
3885 goto error;
3886 }
Michal Vasko0d204592015-10-07 09:50:04 +02003887 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003888 goto error;
3889 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003890 } else if (!strcmp(sub->name, "if-feature")) {
3891 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003892 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003893 goto error;
3894 }
Radek Krejcicf509982015-12-15 09:22:44 +01003895 /* hack - store pointer to the parent node for later status check */
3896 cont->features[cont->features_size] = (struct lys_feature *)cont;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003897 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003898 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003899 cont->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003900 lydict_remove(module->ctx, value);
3901 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003902 goto error;
3903 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003906
Radek Krejcic071c542016-01-27 14:57:51 +01003907 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003908 goto error;
3909 }
3910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 /* last part - process data nodes */
3912 LY_TREE_FOR_SAFE(root.child, next, sub) {
3913 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003914 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003916 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003918 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003920 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003922 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003923 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003924 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003926 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003927 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003928 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003930 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003931 goto error;
3932 }
Radek Krejci73adb602015-07-02 18:07:40 +02003933
Michal Vasko345da0a2015-12-02 10:35:55 +01003934 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003937 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003938
3939error:
3940
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003941 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003943 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003947}
3948
Michal Vasko0d343d12015-08-24 14:57:36 +02003949/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003950static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003951read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003952 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003953{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003954 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003956 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003957 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 int r;
3959 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 /* init */
3962 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003965 if (!grp) {
3966 LOGMEM;
3967 return NULL;
3968 }
Radek Krejci76512572015-08-04 09:47:08 +02003969 grp->nodetype = LYS_GROUPING;
3970 grp->prev = (struct lys_node *)grp;
3971 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003972
Michal Vasko71e1aa82015-08-12 12:17:51 +02003973 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003974 goto error;
3975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003976
Radek Krejcia9544502015-08-14 08:24:29 +02003977 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3978
Radek Krejci1d82ef62015-08-07 14:44:40 +02003979 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003980 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3981 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003982 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003983 continue;
3984 }
3985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 /* data statements */
3987 if (!strcmp(sub->name, "container") ||
3988 !strcmp(sub->name, "leaf-list") ||
3989 !strcmp(sub->name, "leaf") ||
3990 !strcmp(sub->name, "list") ||
3991 !strcmp(sub->name, "choice") ||
3992 !strcmp(sub->name, "uses") ||
3993 !strcmp(sub->name, "grouping") ||
3994 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003995 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003996 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003997
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 /* array counters */
3999 } else if (!strcmp(sub->name, "typedef")) {
4000 c_tpdf++;
4001 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004002 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 goto error;
4004 }
4005 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004007 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4008 if (c_tpdf) {
4009 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004010 if (!grp->tpdf) {
4011 LOGMEM;
4012 goto error;
4013 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004014 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004015 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004016 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4017 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004018 if (r) {
4019 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004020 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004022
Radek Krejcic071c542016-01-27 14:57:51 +01004023 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004024 goto error;
4025 }
4026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 /* last part - process data nodes */
4028 LY_TREE_FOR_SAFE(root.child, next, sub) {
4029 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004030 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004031 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004032 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004034 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004036 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004037 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004038 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004039 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004040 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004042 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004044 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004046 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 goto error;
4048 }
Radek Krejci73adb602015-07-02 18:07:40 +02004049
Michal Vasko345da0a2015-12-02 10:35:55 +01004050 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004053 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004054
4055error:
4056
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004057 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004059 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004060 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004063}
4064
Michal Vasko0d343d12015-08-24 14:57:36 +02004065/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004066static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004067read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4068 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004069{
Radek Krejcie0674f82015-06-15 13:58:51 +02004070 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004071 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004072 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004073 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004074 int r;
4075 int c_tpdf = 0;
4076
Radek Krejcie0674f82015-06-15 13:58:51 +02004077 /* init */
4078 memset(&root, 0, sizeof root);
4079
Michal Vasko38d01f72015-06-15 09:41:06 +02004080 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004081 if (!inout) {
4082 LOGMEM;
4083 return NULL;
4084 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004085 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004086
4087 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004088 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004089 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004090 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004091 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004092 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004093 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004094 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004095 }
4096
Radek Krejci76512572015-08-04 09:47:08 +02004097 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004098
Radek Krejci6a113852015-07-03 16:04:20 +02004099 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004100 goto error;
4101 }
4102
Radek Krejcia9544502015-08-14 08:24:29 +02004103 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4104
Michal Vasko38d01f72015-06-15 09:41:06 +02004105 /* data statements */
4106 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004107 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4108 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004109 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004110 continue;
4111 }
4112
Michal Vasko38d01f72015-06-15 09:41:06 +02004113 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004114 !strcmp(sub->name, "leaf-list") ||
4115 !strcmp(sub->name, "leaf") ||
4116 !strcmp(sub->name, "list") ||
4117 !strcmp(sub->name, "choice") ||
4118 !strcmp(sub->name, "uses") ||
4119 !strcmp(sub->name, "grouping") ||
4120 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004121 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004122 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004124 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004125 } else if (!strcmp(sub->name, "typedef")) {
4126 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004127
Michal Vasko38d01f72015-06-15 09:41:06 +02004128 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004129 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004130 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 }
4132 }
4133
4134 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4135 if (c_tpdf) {
4136 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004137 if (!inout->tpdf) {
4138 LOGMEM;
4139 goto error;
4140 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004141 }
4142
Radek Krejci73adb602015-07-02 18:07:40 +02004143 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004144 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4145 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004146 if (r) {
4147 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004148 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004149 }
4150
Radek Krejcic071c542016-01-27 14:57:51 +01004151 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004152 goto error;
4153 }
4154
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 /* last part - process data nodes */
4156 LY_TREE_FOR_SAFE(root.child, next, sub) {
4157 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004158 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004159 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004160 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004161 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004162 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004163 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004164 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004165 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004166 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004167 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004168 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004169 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004170 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004171 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004172 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004174 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004175 goto error;
4176 }
Radek Krejci73adb602015-07-02 18:07:40 +02004177
Michal Vasko345da0a2015-12-02 10:35:55 +01004178 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004179 }
4180
Michal Vasko38d01f72015-06-15 09:41:06 +02004181 return retval;
4182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004184
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004185 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004186 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004187 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004188 }
4189
4190 return NULL;
4191}
4192
Michal Vasko0d343d12015-08-24 14:57:36 +02004193/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004194static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004195read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4196 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004197{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004198 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004199 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004200 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004201 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004202 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004203 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004204 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004205
Michal Vaskoc6551b32015-06-16 10:51:43 +02004206 memset(&root, 0, sizeof root);
4207
Michal Vasko0ea41032015-06-16 08:53:55 +02004208 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004209 if (!notif) {
4210 LOGMEM;
4211 return NULL;
4212 }
Radek Krejci76512572015-08-04 09:47:08 +02004213 notif->nodetype = LYS_NOTIF;
4214 notif->prev = (struct lys_node *)notif;
4215 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004216
Radek Krejci6a113852015-07-03 16:04:20 +02004217 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004218 goto error;
4219 }
4220
Radek Krejcia9544502015-08-14 08:24:29 +02004221 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4222
Michal Vasko0ea41032015-06-16 08:53:55 +02004223 /* process rpc's specific children */
4224 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004225 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4226 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004227 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004228 continue;
4229 }
4230
Michal Vasko0ea41032015-06-16 08:53:55 +02004231 /* data statements */
4232 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004233 !strcmp(sub->name, "leaf-list") ||
4234 !strcmp(sub->name, "leaf") ||
4235 !strcmp(sub->name, "list") ||
4236 !strcmp(sub->name, "choice") ||
4237 !strcmp(sub->name, "uses") ||
4238 !strcmp(sub->name, "grouping") ||
4239 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004240 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004241 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004243 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004244 } else if (!strcmp(sub->name, "typedef")) {
4245 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004246 } else if (!strcmp(sub->name, "if-feature")) {
4247 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004248 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004249 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004251 }
4252 }
4253
4254 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4255 if (c_tpdf) {
4256 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004257 if (!notif->tpdf) {
4258 LOGMEM;
4259 goto error;
4260 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004261 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004262 if (c_ftrs) {
4263 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004264 if (!notif->features) {
4265 LOGMEM;
4266 goto error;
4267 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004268 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004269
Radek Krejci73adb602015-07-02 18:07:40 +02004270 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004271 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004272 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4273 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004274 if (r) {
4275 goto error;
4276 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004277 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004278 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004279 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004280 goto error;
4281 }
Radek Krejcicf509982015-12-15 09:22:44 +01004282 /* hack - store pointer to the parent node for later status check */
4283 notif->features[notif->features_size] = (struct lys_feature *)notif;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004284 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004285 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004286 notif->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004287 lydict_remove(module->ctx, value);
4288 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004289 goto error;
4290 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004291 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004292 }
4293
Radek Krejcic071c542016-01-27 14:57:51 +01004294 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004295 goto error;
4296 }
4297
Michal Vasko0ea41032015-06-16 08:53:55 +02004298 /* last part - process data nodes */
4299 LY_TREE_FOR_SAFE(root.child, next, sub) {
4300 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004301 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004302 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004303 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004304 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004305 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004306 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004307 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004308 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004309 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004310 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004311 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004312 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004313 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004314 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004315 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004316 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004317 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004318 goto error;
4319 }
Radek Krejci73adb602015-07-02 18:07:40 +02004320
Michal Vasko345da0a2015-12-02 10:35:55 +01004321 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004322 }
4323
Michal Vasko0ea41032015-06-16 08:53:55 +02004324 return retval;
4325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004327
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004328 lys_node_free(retval, NULL);
Michal Vasko0ea41032015-06-16 08:53:55 +02004329 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004330 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004331 }
4332
4333 return NULL;
4334}
4335
Michal Vasko0d343d12015-08-24 14:57:36 +02004336/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004337static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004338read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4339 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004340{
Radek Krejcie0674f82015-06-15 13:58:51 +02004341 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004342 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004343 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004344 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004345 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004346 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004347 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004348
Radek Krejcie0674f82015-06-15 13:58:51 +02004349 /* init */
4350 memset(&root, 0, sizeof root);
4351
Michal Vasko38d01f72015-06-15 09:41:06 +02004352 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004353 if (!rpc) {
4354 LOGMEM;
4355 return NULL;
4356 }
Radek Krejci76512572015-08-04 09:47:08 +02004357 rpc->nodetype = LYS_RPC;
4358 rpc->prev = (struct lys_node *)rpc;
4359 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004360
Radek Krejci6a113852015-07-03 16:04:20 +02004361 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004362 goto error;
4363 }
4364
Radek Krejcia9544502015-08-14 08:24:29 +02004365 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4366
Michal Vasko38d01f72015-06-15 09:41:06 +02004367 /* process rpc's specific children */
4368 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004369 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4370 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004371 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004372 continue;
4373 }
4374
Michal Vasko38d01f72015-06-15 09:41:06 +02004375 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004377 && (rpc->child->nodetype == LYS_INPUT
4378 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004379 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004380 goto error;
4381 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004382 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004383 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004384 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004386 && (rpc->child->nodetype == LYS_INPUT
4387 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004388 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004389 goto error;
4390 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004391 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004392 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004394 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004395 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004396 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004397 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004400 } else if (!strcmp(sub->name, "typedef")) {
4401 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004402 } else if (!strcmp(sub->name, "if-feature")) {
4403 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004404 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004405 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004406 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004407 }
4408 }
4409
4410 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4411 if (c_tpdf) {
4412 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004413 if (!rpc->tpdf) {
4414 LOGMEM;
4415 goto error;
4416 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004417 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004418 if (c_ftrs) {
4419 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004420 if (!rpc->features) {
4421 LOGMEM;
4422 goto error;
4423 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004424 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004425
Radek Krejci73adb602015-07-02 18:07:40 +02004426 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004427 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004428 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4429 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004430 if (r) {
4431 goto error;
4432 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004433 } else if (!strcmp(sub->name, "if-feature")) {
4434 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004435 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004436 goto error;
4437 }
Radek Krejcicf509982015-12-15 09:22:44 +01004438 /* hack - store pointer to the parent node for later status check */
4439 rpc->features[rpc->features_size] = (struct lys_feature *)rpc;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004440 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004441 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004442 rpc->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004443 lydict_remove(module->ctx, value);
4444 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004445 goto error;
4446 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004447 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004448 }
4449
Radek Krejcic071c542016-01-27 14:57:51 +01004450 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004451 goto error;
4452 }
4453
Michal Vasko38d01f72015-06-15 09:41:06 +02004454 /* last part - process data nodes */
4455 LY_TREE_FOR_SAFE(root.child, next, sub) {
4456 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004457 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004458 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004459 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004460 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004461 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004462 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004463 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004464 goto error;
4465 }
Radek Krejci73adb602015-07-02 18:07:40 +02004466
Michal Vasko345da0a2015-12-02 10:35:55 +01004467 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004468 }
4469
Michal Vasko38d01f72015-06-15 09:41:06 +02004470 return retval;
4471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004472error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004473
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004474 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004475 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004476 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004477 }
4478
4479 return NULL;
4480}
4481
Michal Vasko0d343d12015-08-24 14:57:36 +02004482/* logs directly
4483 *
Radek Krejci74705112015-06-05 10:25:44 +02004484 * resolve - referenced grouping should be bounded to the namespace (resolved)
4485 * only when uses does not appear in grouping. In a case of grouping's uses,
4486 * we just get information but we do not apply augment or refine to it.
4487 */
Radek Krejci76512572015-08-04 09:47:08 +02004488static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004489read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004490 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004491{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004493 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004494 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004496 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004500 if (!uses) {
4501 LOGMEM;
4502 return NULL;
4503 }
Radek Krejci76512572015-08-04 09:47:08 +02004504 uses->nodetype = LYS_USES;
4505 uses->prev = (struct lys_node *)uses;
4506 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004507
Radek Krejcia9544502015-08-14 08:24:29 +02004508 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004510
Michal Vaskoe0c59842015-09-24 13:52:20 +02004511 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4512 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 goto error;
4514 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004515
Radek Krejcia9544502015-08-14 08:24:29 +02004516 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004519 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004520 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4521 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004522 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004523 continue;
4524 }
4525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 if (!strcmp(sub->name, "refine")) {
4527 c_ref++;
4528 } else if (!strcmp(sub->name, "augment")) {
4529 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004530 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004531 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004532 } else if (!strcmp(sub->name, "when")) {
4533 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004534 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004535 goto error;
4536 }
4537
4538 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004539 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004540 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004541 goto error;
4542 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004543 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004544 goto error;
4545 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004546 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004547 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004548 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 }
4551 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004553 /* process properties with cardinality 0..n */
4554 if (c_ref) {
4555 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004556 if (!uses->refine) {
4557 LOGMEM;
4558 goto error;
4559 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 }
4561 if (c_aug) {
4562 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004563 if (!uses->augment) {
4564 LOGMEM;
4565 goto error;
4566 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004568 if (c_ftrs) {
4569 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004570 if (!uses->features) {
4571 LOGMEM;
4572 goto error;
4573 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004574 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004575
Radek Krejcic071c542016-01-27 14:57:51 +01004576 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004577 goto error;
4578 }
4579
Radek Krejcia9544502015-08-14 08:24:29 +02004580 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004582 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4583 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004584 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004585 goto error;
4586 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004587 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004588 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4589 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004590 if (r) {
4591 goto error;
4592 }
4593 } else if (!strcmp(sub->name, "if-feature")) {
4594 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004595 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004596 goto error;
4597 }
Radek Krejcicf509982015-12-15 09:22:44 +01004598 /* hack - store pointer to the parent node for later status check */
4599 uses->features[uses->features_size] = (struct lys_feature *)uses;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004600 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02004601 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004602 uses->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004603 lydict_remove(module->ctx, value);
4604 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004605 goto error;
4606 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 }
4608 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004609
Michal Vasko0bd29d12015-08-19 11:45:49 +02004610 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004611 goto error;
4612 }
Radek Krejci74705112015-06-05 10:25:44 +02004613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 if (resolve) {
4615 /* inherit config flag */
4616 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004617 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 } else {
4619 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004620 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 }
4622 }
Radek Krejcib388c152015-06-04 17:03:03 +02004623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004625
4626error:
4627
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004628 lys_node_free(retval, NULL);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004631}
4632
Michal Vasko0d343d12015-08-24 14:57:36 +02004633/* logs directly
4634 *
4635 * common code for yin_read_module() and yin_read_submodule()
4636 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004637static int
Radek Krejcic071c542016-01-27 14:57:51 +01004638read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4639 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004640{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004642 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004643 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004644 struct lys_module *trg;
4645 struct lys_import *aux_imp;
4646 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004648 int i, j, r;
4649 int inc_size_aux = 0;
4650 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004651 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004652 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 +02004653
Radek Krejcic071c542016-01-27 14:57:51 +01004654 /* to simplify code, store the module/submodule being processed as trg */
4655 trg = submodule ? (struct lys_module*)submodule : module;
4656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 /* init */
4658 memset(&root, 0, sizeof root);
4659 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004660 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 /*
4663 * in the first run, we process elements with cardinality of 1 or 0..1 and
4664 * count elements with cardinality 0..n. Data elements (choices, containers,
4665 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4666 * need have all top-level and groupings already prepared at that time. In
4667 * the middle loop, we process other elements with carinality of 0..n since
4668 * we need to allocate arrays to store them.
4669 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004670 LY_TREE_FOR_SAFE(yin->child, next, child) {
4671 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004672 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004673 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 continue;
4675 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004676
Radek Krejcic071c542016-01-27 14:57:51 +01004677 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004679 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004680 goto error;
4681 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004682 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004684 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004685 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004687 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 goto error;
4689 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004691 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 goto error;
4693 }
4694 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004695 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004696 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4697 if (submodule->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004698 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 goto error;
4700 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004703 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 goto error;
4705 }
Radek Krejcif3886932015-06-04 17:36:06 +02004706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004708 if (!child->child) {
4709 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004711 } else if (strcmp(child->child->name, "prefix")) {
4712 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004714 } else if (child->child->next) {
4715 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 goto error;
4717 }
4718 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004719 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004720 /* check here differs from a generic prefix check, since this prefix
4721 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004722 */
Radek Krejcic6556022016-01-27 15:16:45 +01004723 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 goto error;
4725 }
Radek Krejcic071c542016-01-27 14:57:51 +01004726 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004729 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004730
4731 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004732 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004733 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004734 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004736 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004738 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004739 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004740 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004742 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004743 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004744 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004745 lyxml_unlink_elem(ctx, child, 2);
4746 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004747
Radek Krejci1d82ef62015-08-07 14:44:40 +02004748 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004749 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004750 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004751 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004754 } else if (!strcmp(child->name, "container") ||
4755 !strcmp(child->name, "leaf-list") ||
4756 !strcmp(child->name, "leaf") ||
4757 !strcmp(child->name, "list") ||
4758 !strcmp(child->name, "choice") ||
4759 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004760 !strcmp(child->name, "anyxml") ||
4761 !strcmp(child->name, "rpc") ||
4762 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004763 lyxml_unlink_elem(ctx, child, 2);
4764 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004765
Radek Krejci1d82ef62015-08-07 14:44:40 +02004766 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004768 lyxml_unlink_elem(ctx, child, 2);
4769 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004772 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004773 if (trg->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 goto error;
4776 }
Radek Krejcic071c542016-01-27 14:57:51 +01004777 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004778 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004779 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 goto error;
4781 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004782 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004783 if (trg->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004784 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004785 goto error;
4786 }
Radek Krejcic071c542016-01-27 14:57:51 +01004787 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004788 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004789 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004790 goto error;
4791 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004792 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004793 if (trg->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004794 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004795 goto error;
4796 }
Radek Krejcic071c542016-01-27 14:57:51 +01004797 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004798 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004799 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004800 goto error;
4801 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004802 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004803 if (trg->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004804 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004805 goto error;
4806 }
Radek Krejcic071c542016-01-27 14:57:51 +01004807 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004808 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004809 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 goto error;
4811 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004812 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004814 if (version_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004815 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 goto error;
4817 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004818 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004819 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004820 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004821 goto error;
4822 }
Radek Krejcic071c542016-01-27 14:57:51 +01004823 version_flag = 1;
4824 if (!submodule) {
4825 module->version = 1;
4826 } /* 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 +01004827 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004828
Radek Krejci1d82ef62015-08-07 14:44:40 +02004829 } else if (!strcmp(child->name, "extension")) {
4830 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004831
Radek Krejci3d468122015-10-02 13:36:12 +02004832 /* we have the following supported (hardcoded) extensions: */
4833 /* ietf-netconf's get-filter-element-attributes */
4834 if (!strcmp(module->ns, LY_NSNC) &&
4835 !strcmp(value, "get-filter-element-attributes")) {
4836 LOGDBG("NETCONF filter extension found");
4837 /* NACM's default-deny-write and default-deny-all */
4838 } else if (!strcmp(module->ns, LY_NSNACM) &&
4839 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4840 LOGDBG("NACM extension found");
4841 /* other extensions are not supported, so inform about such an extension */
4842 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004843 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004844 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004845 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004846 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004847 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004848 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 }
4850 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004851
Radek Krejcic071c542016-01-27 14:57:51 +01004852 /* check for mandatory statements */
4853 if (submodule && !submodule->prefix) {
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004854 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "belongs-to", "submodule");
4855 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004856 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004858 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 goto error;
4860 }
4861 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004862 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 goto error;
4864 }
4865 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004867 /* allocate arrays for elements with cardinality of 0..n */
4868 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004869 trg->imp = calloc(c_imp, sizeof *trg->imp);
4870 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004871 LOGMEM;
4872 goto error;
4873 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 }
4875 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004876 trg->rev = calloc(c_rev, sizeof *trg->rev);
4877 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004878 LOGMEM;
4879 goto error;
4880 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 }
4882 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004883 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4884 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004885 LOGMEM;
4886 goto error;
4887 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 }
4889 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004890 trg->ident = calloc(c_ident, sizeof *trg->ident);
4891 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004892 LOGMEM;
4893 goto error;
4894 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004895 }
4896 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004897 trg->inc = calloc(c_inc, sizeof *trg->inc);
4898 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004899 LOGMEM;
4900 goto error;
4901 }
Radek Krejcic071c542016-01-27 14:57:51 +01004902 trg->inc_size = c_inc;
4903 /* trg->inc_size can be updated by the included submodules,
4904 * so we will use inc_size_aux here, trg->inc_size stores the
4905 * target size of the array
4906 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004907 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004908 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004909 trg->augment = calloc(c_aug, sizeof *trg->augment);
4910 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004911 LOGMEM;
4912 goto error;
4913 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004914 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004915 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004916 trg->features = calloc(c_ftrs, sizeof *trg->features);
4917 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004918 LOGMEM;
4919 goto error;
4920 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004921 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004922 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004923 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4924 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004925 LOGMEM;
4926 goto error;
4927 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004928 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004929
Michal Vasko2f7925f2015-10-21 15:06:56 +02004930 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4931 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004932 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004933 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4934 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004935 if (r) {
4936 goto error;
4937 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004939 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004940 for (i = 0; i < trg->imp_size - 1; i++) {
4941 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
4942 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004943 goto error;
4944 }
4945 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004946
Radek Krejci1d82ef62015-08-07 14:44:40 +02004947 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004948 memset(&inc, 0, sizeof inc);
4949 /* 1) pass module, not trg, since we want to pass the main module
4950 * 2) we cannot pass directly the structure in the array since
4951 * submodule parser can realloc our array of includes */
4952 r = fill_yin_include(module, child, &inc, unres);
4953 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4954 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 if (r) {
4956 goto error;
4957 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004959 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004960 for (i = 0; i < inc_size_aux - 1; i++) {
4961 if (!strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
4962 LOGVAL(LYE_SPEC, LOGLINE(child), "Including submodule \"%s\" repeatedly.",
4963 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 goto error;
4965 }
4966 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004967
Radek Krejci1d82ef62015-08-07 14:44:40 +02004968 } else if (!strcmp(child->name, "revision")) {
4969 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004970 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971 goto error;
4972 }
Radek Krejcic071c542016-01-27 14:57:51 +01004973 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004975 for (i = 0; i < trg->rev_size; i++) {
4976 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004977 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004978 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 }
4980 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004981
Radek Krejci1d82ef62015-08-07 14:44:40 +02004982 LY_TREE_FOR(child->child, child2) {
4983 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004984 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004985 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 goto error;
4987 }
Radek Krejcic071c542016-01-27 14:57:51 +01004988 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4989 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004990 goto error;
4991 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004992 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004993 if (trg->rev[trg->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004994 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004995 goto error;
4996 }
Radek Krejcic071c542016-01-27 14:57:51 +01004997 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4998 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999 goto error;
5000 }
5001 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005002 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 goto error;
5004 }
5005 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005008 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005009 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005010 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005011 if (!value) {
5012 LOGMEM;
5013 goto error;
5014 }
Radek Krejcic071c542016-01-27 14:57:51 +01005015 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5016 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005018
Radek Krejcic071c542016-01-27 14:57:51 +01005019 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
5020 value = trg->rev[0].dsc;
5021 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5022 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005024
Radek Krejcic071c542016-01-27 14:57:51 +01005025 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
5026 value = trg->rev[0].ref;
5027 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5028 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005029 }
5030 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005031
Radek Krejcic071c542016-01-27 14:57:51 +01005032 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005033
Radek Krejci1d82ef62015-08-07 14:44:40 +02005034 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005035 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5036 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 if (r) {
5038 goto error;
5039 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005040
Radek Krejci1d82ef62015-08-07 14:44:40 +02005041 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005042 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5043 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 if (r) {
5045 goto error;
5046 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005047
Radek Krejci1d82ef62015-08-07 14:44:40 +02005048 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005049 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5050 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005051 if (r) {
5052 goto error;
5053 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005054
Radek Krejci1d82ef62015-08-07 14:44:40 +02005055 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005056 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5057 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005058 if (r) {
5059 goto error;
5060 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005062 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005063 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005064
Radek Krejcic071c542016-01-27 14:57:51 +01005065 if (submodule) {
5066 /* propagate imports into the main module */
5067 for (i = r = 0; i < submodule->imp_size; i++) {
5068 for (j = 0; j < module->imp_size; j++) {
5069 if (submodule->imp[i].module == module->imp[j].module &&
5070 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5071 /* check prefix match */
5072 if (submodule->imp[i].prefix != module->imp[j].prefix) {
5073 LOGVAL(LYE_INID, LOGLINE(yin), submodule->imp[i].prefix,
5074 "non-matching prefixes of imported module in main module and submodule");
5075 goto error;
5076 }
5077 break;
5078 }
5079 }
5080 if (j == module->imp_size) {
5081 /* new import */
5082 r++;
5083 }
5084 }
5085 if (r) {
5086 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5087 if (!aux_imp) {
5088 LOGMEM;
5089 goto error;
5090 }
5091 module->imp = aux_imp;
5092 for (i = r = 0; i < submodule->imp_size; i++) {
5093 for (j = 0; j < module->imp_size; j++) {
5094 if (submodule->imp[i].module == module->imp[j].module) {
5095 break;
5096 }
5097 }
5098 if (j == module->imp_size) {
5099 /* new import */
5100 /* check prefix uniqueness */
5101 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
5102 LOGVAL(LYE_DUPID, LOGLINE(yin), "prefix", submodule->imp[i].prefix);
5103 goto error;
5104 }
5105 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5106 module->imp[module->imp_size + r].external = 1;
5107 r++;
5108 }
5109 }
5110 module->imp_size += r;
5111 }
5112
5113 /* propagate imports into the main module */
5114 for (i = r = 0; i < submodule->inc_size; i++) {
5115 for (j = 0; j < module->inc_size; j++) {
5116 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5117 break;
5118 }
5119 }
5120 if (j == module->inc_size) {
5121 /* new include */
5122 r++;
5123 }
5124 }
5125
5126 if (r) {
5127 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5128 if (!aux_inc) {
5129 LOGMEM;
5130 goto error;
5131 }
5132 module->inc = aux_inc;
5133 for (i = r = 0; i < submodule->inc_size; i++) {
5134 for (j = 0; j < module->inc_size; j++) {
5135 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5136 break;
5137 }
5138 }
5139 if (j == module->inc_size) {
5140 /* new include */
5141 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5142 module->inc[module->inc_size + r].external = 1;
5143 r++;
5144 }
5145 }
5146 module->inc_size += r;
5147 }
5148 }
5149
Radek Krejcif5be10f2015-06-16 13:29:36 +02005150 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005151 * refer to them. Submodule's data nodes are stored in the
5152 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005153 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005154 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005155 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005156 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005157 goto error;
5158 }
Radek Krejci74705112015-06-05 10:25:44 +02005159
Michal Vasko345da0a2015-12-02 10:35:55 +01005160 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 }
Radek Krejci74705112015-06-05 10:25:44 +02005162
Radek Krejcif5be10f2015-06-16 13:29:36 +02005163 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005164 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005165
Radek Krejci1d82ef62015-08-07 14:44:40 +02005166 if (!strcmp(child->name, "container")) {
5167 node = read_yin_container(module, NULL, child, 1, unres);
5168 } else if (!strcmp(child->name, "leaf-list")) {
5169 node = read_yin_leaflist(module, NULL, child, 1, unres);
5170 } else if (!strcmp(child->name, "leaf")) {
5171 node = read_yin_leaf(module, NULL, child, 1, unres);
5172 } else if (!strcmp(child->name, "list")) {
5173 node = read_yin_list(module, NULL, child, 1, unres);
5174 } else if (!strcmp(child->name, "choice")) {
5175 node = read_yin_choice(module, NULL, child, 1, unres);
5176 } else if (!strcmp(child->name, "uses")) {
5177 node = read_yin_uses(module, NULL, child, 1, unres);
5178 } else if (!strcmp(child->name, "anyxml")) {
5179 node = read_yin_anyxml(module, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005180 } else if (!strcmp(child->name, "rpc")) {
5181 node = read_yin_rpc(module, NULL, child, 0, unres);
5182 } else if (!strcmp(child->name, "notification")) {
5183 node = read_yin_notif(module, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005184 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005185 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005186 goto error;
5187 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005188
Michal Vasko345da0a2015-12-02 10:35:55 +01005189 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005191
Michal Vasko2f7925f2015-10-21 15:06:56 +02005192 /* ... and finally augments (last, so we can augment our data, for instance) */
5193 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005194 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5195 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005196
Michal Vasko2f7925f2015-10-21 15:06:56 +02005197 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005198 goto error;
5199 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005200 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005201 }
5202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005203 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005204
5205error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005206 /* cleanup */
5207 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005208 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005209 }
5210 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005211 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005212 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005213 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005214 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005215 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005218}
5219
Michal Vasko0d343d12015-08-24 14:57:36 +02005220/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005221struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01005222yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005223{
Michal Vasko9f258e42016-02-11 11:36:27 +01005224 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005226 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005227 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005228 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005231
Radek Krejci722b0072016-02-01 17:09:45 +01005232 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 if (!yin) {
5234 return NULL;
5235 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005237 /* check root element */
5238 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005239 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005240 goto error;
5241 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005244 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005245 goto error;
5246 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005248 submodule = calloc(1, sizeof *submodule);
5249 if (!submodule) {
5250 LOGMEM;
5251 goto error;
5252 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 submodule->ctx = module->ctx;
5255 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5256 submodule->type = 1;
5257 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005258
Michal Vasko9f258e42016-02-11 11:36:27 +01005259 LOGVRB("Reading submodule \"%s\".", submodule->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005260 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 goto error;
5262 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005265 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005266
Michal Vasko9f258e42016-02-11 11:36:27 +01005267 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005270
5271error:
Michal Vasko9f258e42016-02-11 11:36:27 +01005272 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
5273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005275 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005276 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005277
5278 /* warn about applied deviations */
5279 for (i = 0; i < submodule->deviation_size; ++i) {
5280 if (submodule->deviation[i].target) {
5281 LOGERR(ly_errno, "Submodule parsing failed, but successfully deviated %smodule \"%s\".",
5282 (submodule->deviation[i].target->module->type ? "sub" : ""),
5283 submodule->deviation[i].target->module->name);
5284 }
5285 }
5286
5287 /* remove applied augments */
5288 for (i = 0; i < submodule->augment_size; ++i) {
5289 if (submodule->augment[i].target) {
5290 LY_TREE_FOR_SAFE(submodule->augment[i].target->child, next, elem) {
5291 if (elem->parent == (struct lys_node *)&submodule->augment[i]) {
5292 lys_node_free(elem, NULL);
5293 }
5294 }
5295 }
5296 }
5297
5298 lys_submodule_free(submodule, NULL);
Radek Krejciefaeba32015-05-27 14:30:57 +02005299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005301}
5302
Michal Vasko0d343d12015-08-24 14:57:36 +02005303/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005304struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005305yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005306{
Michal Vasko9f258e42016-02-11 11:36:27 +01005307 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005309 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005310 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005311 const char *value;
5312 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005313
Radek Krejcic071c542016-01-27 14:57:51 +01005314 unres = calloc(1, sizeof *unres);
5315 if (!unres) {
5316 LOGMEM;
5317 return NULL;
5318 }
5319
Radek Krejci722b0072016-02-01 17:09:45 +01005320 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005321 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005322 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005323 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005325 /* check root element */
5326 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005327 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005328 goto error;
5329 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005331 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005332 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 goto error;
5334 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005336 module = calloc(1, sizeof *module);
5337 if (!module) {
5338 LOGMEM;
5339 goto error;
5340 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 module->ctx = ctx;
5343 module->name = lydict_insert(ctx, value, strlen(value));
5344 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005345 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005346
Michal Vasko9f258e42016-02-11 11:36:27 +01005347 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005348 if (read_sub_module(module, NULL, yin, unres)) {
5349 goto error;
5350 }
5351
5352 /* resolve rest of unres items */
5353 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005354 goto error;
5355 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 /* add to the context's list of modules */
5358 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005359 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 if (!newlist) {
5361 LOGMEM;
5362 goto error;
5363 }
5364 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5365 newlist[i] = NULL;
5366 }
5367 ctx->models.size *= 2;
5368 ctx->models.list = newlist;
5369 }
5370 for (i = 0; ctx->models.list[i]; i++) {
5371 /* check name (name/revision) and namespace uniqueness */
5372 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005373 if (ctx->models.list[i]->rev_size == module->rev_size) {
5374 /* both have the same number of revisions */
5375 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5376 /* both have the same revision -> we already have the same module */
5377 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005378 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005379
Michal Vasko9f258e42016-02-11 11:36:27 +01005380 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005381 module = ctx->models.list[i];
5382 if (implement && !module->implemented) {
5383 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005384 }
Radek Krejcic071c542016-01-27 14:57:51 +01005385
5386 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005387 }
5388 }
Radek Krejcif647e612015-07-30 11:36:07 +02005389 /* else (both elses) keep searching, for now the caller is just adding
5390 * another revision of an already present schema
5391 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005392 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005393 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005394 ctx->models.list[i]->name, module->name, module->ns);
5395 goto error;
5396 }
5397 }
5398 ctx->models.list[i] = module;
5399 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005400 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005401
Radek Krejcic071c542016-01-27 14:57:51 +01005402success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005403 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005404 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005405 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005406
Michal Vasko9f258e42016-02-11 11:36:27 +01005407 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005409 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005410
5411error:
Michal Vasko9f258e42016-02-11 11:36:27 +01005412 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
5413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005414 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005415 unres_schema_free(module, &unres);
Radek Krejcic071c542016-01-27 14:57:51 +01005416 lyxml_free(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005417
Michal Vasko9f258e42016-02-11 11:36:27 +01005418 /* warn about applied deviations */
5419 for (i = 0; i < module->deviation_size; ++i) {
5420 if (module->deviation[i].target) {
5421 LOGERR(ly_errno, "Module parsing failed, but successfully deviated %smodule \"%s\".",
5422 (module->deviation[i].target->module->type ? "sub" : ""),
5423 module->deviation[i].target->module->name);
5424 }
5425 }
5426
5427 /* remove applied augments */
5428 for (i = 0; i < module->augment_size; ++i) {
5429 if (module->augment[i].target) {
5430 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5431 if (elem->parent == (struct lys_node *)&module->augment[i]) {
5432 lys_node_free(elem, NULL);
5433 }
5434 }
5435 }
5436 }
5437
5438 lys_free(module, NULL, 1);
5439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005440 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005441}