blob: 5f55ef924f0851959fe3ffef329d291da3fec2e4 [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;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100371 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200372 p++;
373 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200374
375 /* keep them ordered by position */
376 j = i;
377 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
378 /* switch them */
379 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
380 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
381 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
382 j--;
383 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200384 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200385 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200387 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200388 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200389 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200390 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
391 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200392 continue;
393 }
394
Radek Krejcif9401c32015-06-26 16:47:36 +0200395 if (!strcmp(node->name, "range")) {
396 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200397 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200398 goto error;
399 }
400
401 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200402 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200403 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200404 goto error;
405 }
406 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100407 if (!type->info.dec64.range) {
408 LOGMEM;
409 goto error;
410 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200411 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
412
413 /* get possible substatements */
414 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
415 goto error;
416 }
417 } else if (!strcmp(node->name, "fraction-digits")) {
418 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200419 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200420 goto error;
421 }
422 GETVAL(value, node, "value");
423 v = strtol(value, NULL, 10);
424
425 /* range check */
426 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200427 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200428 goto error;
429 }
430 type->info.dec64.dig = (uint8_t)v;
431 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200432 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200433 goto error;
434 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200435 }
436
437 /* mandatory sub-statement(s) check */
438 if (!type->info.dec64.dig && !type->der->type.der) {
439 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200440 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200441 goto error;
442 }
Radek Krejci7511f402015-07-10 09:56:30 +0200443 if (type->info.dec64.dig && type->der->type.der) {
444 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200445 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200446 goto error;
447 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200448 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200450 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200451 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200452
Radek Krejci994b6f62015-06-18 16:47:27 +0200453 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200454 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200455 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
456 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100457 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200458 continue;
459 }
460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200461 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200462 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200463 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100464 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200465 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200466 }
467 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200468 if (!type->der->type.der && !type->info.enums.count) {
469 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200470 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200471 goto error;
472 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200473 if (type->der->type.der && type->info.enums.count) {
474 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200475 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200476 goto error;
477 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200478
Radek Krejci1574a8d2015-08-03 14:16:52 +0200479 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100480 if (!type->info.enums.enm) {
481 LOGMEM;
482 goto error;
483 }
Radek Krejci73adb602015-07-02 18:07:40 +0200484 v = 0;
485 i = -1;
486 LY_TREE_FOR(yin->child, next) {
487 i++;
488
489 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100490 if (!value[0]) {
491 LOGVAL(LYE_SPEC, LOGLINE(next), "Enum name must not be empty.");
492 goto error;
493 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200494 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200495 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200496 type->info.enums.count = i + 1;
497 goto error;
498 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200500 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200501 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200502 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200503 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200504 type->info.enums.count = i + 1;
505 goto error;
506 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200508 /* check the name uniqueness */
509 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200510 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200511 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200512 type->info.enums.count = i + 1;
513 goto error;
514 }
515 }
Radek Krejci04581c62015-05-22 21:24:00 +0200516
Radek Krejci0d70c372015-07-02 16:23:10 +0200517 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200518 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200519 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
520 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200521 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200522 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200523
Radek Krejci0d70c372015-07-02 16:23:10 +0200524 if (!strcmp(node->name, "value")) {
525 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200526 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200527
528 /* range check */
529 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200530 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200531 type->info.enums.count = i + 1;
532 goto error;
533 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200534 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200535
536 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200537 if (type->info.enums.enm[i].value > v) {
538 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200539 v++;
540 } else {
541 /* check that the value is unique */
542 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200543 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200544 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200545 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200546 type->info.enums.count = i + 1;
547 goto error;
548 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200549 }
550 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200551 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100552 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200553 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200554 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200555 }
556 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557 /* assign value automatically */
558 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200559 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200560 type->info.enums.count = i + 1;
561 goto error;
562 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200563 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100564 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200565 v++;
566 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200567 }
568 break;
569
570 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200571 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200572
573 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200574 LY_TREE_FOR_SAFE(yin->child, next, node) {
575 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
576 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100577 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200578 continue;
579 }
580
Michal Vaskoe29c6622015-11-27 15:02:31 +0100581 if (strcmp(node->name, "base")) {
582 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200583 goto error;
584 }
585 }
586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200588 if (type->der->type.der) {
589 /* this is just a derived type with no base specified/required */
590 break;
591 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200592 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200593 goto error;
594 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200596 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 goto error;
598 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200599 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100600 /* store in the JSON format */
601 value = transform_schema2json(module, value, LOGLINE(yin->child));
602 if (!value) {
603 goto error;
604 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200605 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200606 goto error;
607 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200608 break;
609
610 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200611 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200612 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200613 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
614 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200615 continue;
616 }
617
Radek Krejciaf351422015-06-19 14:49:38 +0200618 if (!strcmp(node->name, "require-instance")) {
619 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200620 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200621 goto error;
622 }
623 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200624 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200625 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200626 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200627 type->info.inst.req = -1;
628 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200629 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200630 goto error;
631 }
632 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200633 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200634 goto error;
635 }
Radek Krejciaf351422015-06-19 14:49:38 +0200636 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 break;
639
Radek Krejcif2860132015-06-20 12:37:20 +0200640 case LY_TYPE_BINARY:
641 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 case LY_TYPE_INT8:
643 case LY_TYPE_INT16:
644 case LY_TYPE_INT32:
645 case LY_TYPE_INT64:
646 case LY_TYPE_UINT8:
647 case LY_TYPE_UINT16:
648 case LY_TYPE_UINT32:
649 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200650 /* RFC 6020 9.2.4 - range */
651
652 /* length and range are actually the same restriction, so process
653 * them by this common code, we just need to differ the name and
654 * structure where the information will be stored
655 */
656 if (type->base == LY_TYPE_BINARY) {
657 restr = &type->info.binary.length;
658 name = "length";
659 } else {
660 restr = &type->info.num.range;
661 name = "range";
662 }
663
Radek Krejci73adb602015-07-02 18:07:40 +0200664 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200665 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
666 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200667 continue;
668 }
669
Radek Krejcif2860132015-06-20 12:37:20 +0200670 if (!strcmp(node->name, name)) {
671 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200672 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200673 goto error;
674 }
675
676 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200677 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200678 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200679 goto error;
680 }
681 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100682 if (!(*restr)) {
683 LOGMEM;
684 goto error;
685 }
Radek Krejcif2860132015-06-20 12:37:20 +0200686 (*restr)->expr = lydict_insert(module->ctx, value, 0);
687
688 /* get possible substatements */
689 if (read_restr_substmt(module->ctx, *restr, node)) {
690 goto error;
691 }
692 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200693 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200694 goto error;
695 }
Radek Krejcif2860132015-06-20 12:37:20 +0200696 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200697 break;
698
699 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200700 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200701 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200702 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
703 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200704 continue;
705 }
706
Michal Vasko88c29542015-11-27 14:57:53 +0100707 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200708 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200709 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200710 goto error;
711 }
712
713 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200714 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200715 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200716 if (!type->info.lref.path) {
717 goto error;
718 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200719 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200720 goto error;
721 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200722
Radek Krejcidc4c1412015-06-19 15:39:54 +0200723 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200724 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200725 goto error;
726 }
Radek Krejci73adb602015-07-02 18:07:40 +0200727 }
728
Michal Vasko88c29542015-11-27 14:57:53 +0100729 if (!type->info.lref.path && !type->der->type.der) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200730 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200731 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200732 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 break;
734
735 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200736 /* RFC 6020 9.4.4 - length */
737 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200738 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200739 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200740 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
741 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100742 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200743 continue;
744 }
745
Radek Krejci3733a802015-06-19 13:43:21 +0200746 if (!strcmp(node->name, "length")) {
747 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200748 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200749 goto error;
750 }
751
752 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200753 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200754 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200755 goto error;
756 }
757 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100758 if (!type->info.str.length) {
759 LOGMEM;
760 goto error;
761 }
Radek Krejci3733a802015-06-19 13:43:21 +0200762 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
763
Radek Krejci5fbc9162015-06-19 14:11:11 +0200764 /* get possible sub-statements */
765 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200766 goto error;
767 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100768 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200769 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200770 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200771 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200772 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200773 goto error;
774 }
775 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200776 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200777 if (i) {
778 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100779 if (!type->info.str.patterns) {
780 LOGMEM;
781 goto error;
782 }
Radek Krejci73adb602015-07-02 18:07:40 +0200783 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100784 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200785
786 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200787 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
788 if (!precomp) {
789 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200790 free(type->info.str.patterns);
791 goto error;
792 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200793 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200794
Radek Krejci73adb602015-07-02 18:07:40 +0200795 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200796
797 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100798 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200799 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200800 goto error;
801 }
Radek Krejci73adb602015-07-02 18:07:40 +0200802 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200803 }
804 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200805 break;
806
807 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200808 /* RFC 6020 7.4 - type */
809 /* count number of types in union */
810 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200811 LY_TREE_FOR_SAFE(yin->child, next, node) {
812 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
813 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100814 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200815 continue;
816 }
817
Radek Krejcie4c366b2015-07-02 10:11:31 +0200818 if (!strcmp(node->name, "type")) {
819 i++;
820 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200821 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200822 goto error;
823 }
824 }
825
826 if (!i) {
827 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100828 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200829 break;
830 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200831 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200832 goto error;
833 }
834
835 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200836 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100837 if (!type->info.uni.types) {
838 LOGMEM;
839 goto error;
840 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200841 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200842 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100843 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100844 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
845 if (!rc) {
846 type->info.uni.count++;
847
848 /* union's type cannot be empty or leafref */
849 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
850 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
851 rc = -1;
852 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
853 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
854 rc = -1;
855 }
856 }
857 if (rc) {
858 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
859 for (i = 0; i < type->info.uni.count; ++i) {
860 lys_type_free(module->ctx, &type->info.uni.types[i]);
861 }
862 free(type->info.uni.types);
863 type->info.uni.types = NULL;
864 type->info.uni.count = 0;
865
866 if (rc == EXIT_FAILURE) {
867 return EXIT_FAILURE;
868 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200869 goto error;
870 }
Michal Vasko88c29542015-11-27 14:57:53 +0100871 }
872 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200873
Michal Vasko88c29542015-11-27 14:57:53 +0100874 case LY_TYPE_BOOL:
875 case LY_TYPE_EMPTY:
876 /* no sub-statement allowed */
877 LY_TREE_FOR(yin->child, node) {
878 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
879 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200880 goto error;
881 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200882 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 break;
884
885 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100886 LOGINT;
887 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200888 }
889
890 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200891
892error:
Michal Vasko88c29542015-11-27 14:57:53 +0100893 return -1;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200894}
895
Michal Vasko0d343d12015-08-24 14:57:36 +0200896/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200898fill_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 +0200899{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100901 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200902 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200904 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100905 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200906 goto error;
907 }
908 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200910 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +0200911 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200912 goto error;
913 }
Radek Krejcieac35532015-05-31 19:09:15 +0200914
Michal Vasko88c29542015-11-27 14:57:53 +0100915 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200916 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
917 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200918 continue;
919 }
920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100922 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200923 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200924 goto error;
925 }
Michal Vasko88c29542015-11-27 14:57:53 +0100926 /* HACK for unres */
927 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100928 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100929 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200930 goto error;
931 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200932 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200933 } else if (!strcmp(node->name, "default")) {
934 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200935 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936 goto error;
937 }
938 GETVAL(value, node, "value");
939 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200940 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 } else if (!strcmp(node->name, "units")) {
942 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200943 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 goto error;
945 }
946 GETVAL(value, node, "name");
947 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
948 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200949 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 goto error;
951 }
952 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200955 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200956 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 goto error;
958 }
Radek Krejcieac35532015-05-31 19:09:15 +0200959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200961 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +0200962 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200963 goto error;
964 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200967 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200968
969error:
970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200971 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200972}
973
Michal Vasko0d343d12015-08-24 14:57:36 +0200974/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +0200975static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200976fill_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 +0200977{
978 const char *value;
979 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +0200980 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +0200981
Radek Krejcib05774c2015-06-18 13:52:59 +0200982 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100983 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +0200984 goto error;
985 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200986 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +0200987 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +0200988
Radek Krejci76512572015-08-04 09:47:08 +0200989 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +0200990 goto error;
991 }
992
993 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200994 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
995 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100996 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +0200997 continue;
998 }
999
Radek Krejci3cf9e222015-06-18 11:37:50 +02001000 if (!strcmp(child->name, "if-feature")) {
1001 c++;
1002 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001003 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001004 goto error;
1005 }
1006 }
1007
1008 if (c) {
1009 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001010 if (!f->features) {
1011 LOGMEM;
1012 goto error;
1013 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001014 }
Radek Krejci73adb602015-07-02 18:07:40 +02001015 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001016 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001017 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001018 goto error;
1019 }
Radek Krejcicf509982015-12-15 09:22:44 +01001020 /* hack - store pointer to the parent node for later status check */
1021 f->features[f->features_size] = f;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001022 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001023 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001024 f->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001025 lydict_remove(module->ctx, value);
1026 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001027 goto error;
1028 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001029 }
1030
Radek Krejci3cf9e222015-06-18 11:37:50 +02001031 return EXIT_SUCCESS;
1032
1033error:
1034
1035 return EXIT_FAILURE;
1036}
1037
Michal Vasko0d343d12015-08-24 14:57:36 +02001038/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039static int
Radek Krejcib8048692015-08-05 13:36:34 +02001040fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001041{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001045 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001046 if (!must->expr) {
1047 goto error;
1048 }
Radek Krejci800af702015-06-02 13:46:01 +02001049
Radek Krejci41726f92015-06-19 13:11:05 +02001050 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001051
Radek Krejci41726f92015-06-19 13:11:05 +02001052error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001055}
1056
Radek Krejci581ce772015-11-10 17:22:40 +01001057static int
Michal Vasko88c29542015-11-27 14:57:53 +01001058fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1059 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001060{
1061 int i, j;
1062 const char *value, *vaux;
1063
1064 /* get unique value (list of leafs supposed to be unique */
1065 GETVAL(value, yin, "tag");
1066
1067 /* count the number of unique leafs in the value */
1068 vaux = value;
1069 while ((vaux = strpbrk(vaux, " \t\n"))) {
1070 unique->expr_size++;
1071 while (isspace(*vaux)) {
1072 vaux++;
1073 }
1074 }
1075 unique->expr_size++;
1076 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001077 if (!unique->expr) {
1078 LOGMEM;
1079 goto error;
1080 }
Radek Krejci581ce772015-11-10 17:22:40 +01001081
1082 for (i = 0; i < unique->expr_size; i++) {
1083 vaux = strpbrk(value, " \t\n");
1084 if (!vaux) {
1085 /* the last token, lydict_insert() will count its size on its own */
1086 vaux = value;
1087 }
1088
1089 /* store token into unique structure */
1090 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1091
1092 /* check that the expression does not repeat */
1093 for (j = 0; j < i; j++) {
1094 if (unique->expr[j] == unique->expr[i]) {
1095 LOGVAL(LYE_INARG, LOGLINE(yin), unique->expr[i], "unique");
1096 LOGVAL(LYE_SPEC, 0, "The identifier is not unique");
1097 goto error;
1098 }
1099 }
1100
1101 /* try to resolve leaf */
1102 if (unres) {
1103 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1104 } else {
1105 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1106 goto error;
1107 }
1108 }
1109
1110 /* move to next token */
1111 value = vaux;
1112 while(isspace(*value)) {
1113 value++;
1114 }
1115 }
1116
1117 return EXIT_SUCCESS;
1118
1119error:
1120 return EXIT_FAILURE;
1121}
1122
Michal Vasko0d343d12015-08-24 14:57:36 +02001123/* logs directly
1124 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001125 * type: 0 - min, 1 - max
1126 */
1127static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001128deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001129{
1130 const char *value;
1131 char *endptr;
1132 unsigned long val;
1133 uint32_t *ui32val;
1134
1135 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001136 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001137 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001138 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001139 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001140 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001141 }
Radek Krejci76512572015-08-04 09:47:08 +02001142 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001143 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001144 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001145 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001146 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001147 }
1148 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001149 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1150 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001151 goto error;
1152 }
1153
1154 GETVAL(value, node, "value");
1155 while (isspace(value[0])) {
1156 value++;
1157 }
1158
Radek Krejci0d7b2472016-02-12 11:11:03 +01001159 if (type && !strcmp(value, "unbounded")) {
1160 d->max = val = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001161 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001162 /* convert it to uint32_t */
1163 errno = 0;
1164 endptr = NULL;
1165 val = strtoul(value, &endptr, 10);
1166 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
1167 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1168 goto error;
1169 }
1170 if (type) {
1171 d->max = (uint32_t)val;
1172 } else {
1173 d->min = (uint32_t)val;
1174 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001175 }
1176
1177 if (d->mod == LY_DEVIATE_ADD) {
1178 /* check that there is no current value */
1179 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001180 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1181 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001182 goto error;
1183 }
1184 }
1185
1186 if (d->mod == LY_DEVIATE_DEL) {
1187 /* check values */
1188 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001189 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1190 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001191 goto error;
1192 }
1193 /* remove current min-elements value of the target */
1194 *ui32val = 0;
1195 } else { /* add (already checked) and replace */
1196 /* set new value specified in deviation */
1197 *ui32val = (uint32_t)val;
1198 }
1199
1200 return EXIT_SUCCESS;
1201
1202error:
1203
1204 return EXIT_FAILURE;
1205}
1206
Michal Vasko0d343d12015-08-24 14:57:36 +02001207/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001208static int
Michal Vasko88c29542015-11-27 14:57:53 +01001209fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1210 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001211{
1212 const char *value, **stritem;
1213 struct lyxml_elem *next, *child, *develem;
1214 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001215 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001216 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001217 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001218 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001219 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001220 struct lys_node_choice *choice = NULL;
1221 struct lys_node_leaf *leaf = NULL;
1222 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001223 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001224 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001225 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001226
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001227 ctx = module->ctx;
1228
Radek Krejcieb00f512015-07-01 16:44:58 +02001229 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001230 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001231 if (!dev->target_name) {
1232 goto error;
1233 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001234
1235 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001236 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1237 if (rc || !dev_target) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001238 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001239 goto error;
1240 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001241 if (dev_target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001242 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001243 goto error;
1244 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001245 dev->target_module = dev_target->module;
Radek Krejcieb00f512015-07-01 16:44:58 +02001246 /* mark the target module as deviated */
Michal Vasko60f4b452016-02-12 11:02:55 +01001247 dev->target_module->deviated = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001248
1249 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001250 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1251 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001252 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001253 continue;
1254 }
1255
Radek Krejcieb00f512015-07-01 16:44:58 +02001256 if (!strcmp(child->name, "description")) {
1257 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001258 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001259 goto error;
1260 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001261 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001262 if (!dev->dsc) {
1263 goto error;
1264 }
1265 } else if (!strcmp(child->name, "reference")) {
1266 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001267 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001268 goto error;
1269 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001270 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001271 if (!dev->ref) {
1272 goto error;
1273 }
1274 } else if (!strcmp(child->name, "deviate")) {
1275 c_dev++;
1276
Michal Vasko345da0a2015-12-02 10:35:55 +01001277 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001278 * further processed later
1279 */
1280 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001281
Radek Krejcieb00f512015-07-01 16:44:58 +02001282 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001283 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001284 goto error;
1285 }
1286
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001287 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001288 }
1289
1290 if (c_dev) {
1291 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001292 if (!dev->deviate) {
1293 LOGMEM;
1294 goto error;
1295 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001296 }
1297
1298 LY_TREE_FOR(yin->child, develem) {
1299 /* init */
1300 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001301 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001302 c_must = 0;
1303 c_uniq = 0;
1304
1305 /* get deviation type */
1306 GETVAL(value, develem, "value");
1307 if (!strcmp(value, "not-supported")) {
1308 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1309 /* no property expected in this case */
1310 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001311 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001312 goto error;
1313 }
1314
Radek Krejci5b917642015-07-02 09:03:13 +02001315 /* and neither any other deviate statement is expected,
1316 * not-supported deviation must be the only deviation of the target
1317 */
1318 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001319 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1320 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001321 goto error;
1322 }
1323
1324
Radek Krejcieb00f512015-07-01 16:44:58 +02001325 /* remove target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001326 lys_node_free(dev_target, NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02001327
Radek Krejci5b917642015-07-02 09:03:13 +02001328 dev->deviate_size = 1;
1329 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001330 } else if (!strcmp(value, "add")) {
1331 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1332 } else if (!strcmp(value, "replace")) {
1333 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1334 } else if (!strcmp(value, "delete")) {
1335 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1336 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001337 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001338 goto error;
1339 }
1340 d = &dev->deviate[dev->deviate_size];
1341
1342 /* process deviation properties */
1343 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001344 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1345 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001346 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001347 continue;
1348 }
1349
Radek Krejcieb00f512015-07-01 16:44:58 +02001350 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001351 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001352 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001353 goto error;
1354 }
1355
1356 /* for we deviate from RFC 6020 and allow config property even it is/is not
1357 * specified in the target explicitly since config property inherits. So we expect
1358 * that config is specified in every node. But for delete, we check that the value
1359 * is the same as here in deviation
1360 */
1361 GETVAL(value, child, "value");
1362 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001363 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001364 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001365 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001366 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001367 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001368 goto error;
1369 }
1370
1371 if (d->mod == LY_DEVIATE_DEL) {
1372 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001373 if ((d->flags & LYS_CONFIG_MASK) != (dev_target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001374 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1375 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001376 goto error;
1377 }
1378 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001379 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001380
1381 /* ... and inherit config value from the target's parent */
Michal Vasko60f4b452016-02-12 11:02:55 +01001382 if (dev_target->parent) {
1383 dev_target->flags |= dev_target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001384 } else {
1385 /* default config is true */
Michal Vasko60f4b452016-02-12 11:02:55 +01001386 dev_target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001387 }
1388 } else { /* add and replace are the same in this case */
1389 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001390 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001391
1392 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001393 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001394 }
1395 } else if (!strcmp(child->name, "default")) {
1396 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001397 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001398 goto error;
1399 }
1400 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001401 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001402
Michal Vasko60f4b452016-02-12 11:02:55 +01001403 if (dev_target->nodetype == LYS_CHOICE) {
1404 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001405
1406 if (d->mod == LY_DEVIATE_ADD) {
1407 /* check that there is no current value */
1408 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001409 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1410 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001411 goto error;
1412 }
1413 }
1414
Michal Vasko3edeaf72016-02-11 13:17:43 +01001415 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001416 if (rc || !node) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001417 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1418 goto error;
1419 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001420 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001421 if (!choice->dflt || (choice->dflt != node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001422 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1423 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001424 goto error;
1425 }
1426 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001427 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001428 if (!choice->dflt) {
1429 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001430 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001431 goto error;
1432 }
1433 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001434 } else if (dev_target->nodetype == LYS_LEAF) {
1435 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001436
1437 if (d->mod == LY_DEVIATE_ADD) {
1438 /* check that there is no current value */
1439 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001440 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1441 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001442 goto error;
1443 }
1444 }
1445
1446 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001447 if (!leaf->dflt || (leaf->dflt != d->dflt)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001448 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1449 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001450 goto error;
1451 }
1452 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001453 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 leaf->dflt = NULL;
1455 } else { /* add (already checked) and replace */
1456 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001457 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001458
1459 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001460 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001461 }
1462 } else {
1463 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001464 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1465 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001466 goto error;
1467 }
1468 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001469 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001470 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 goto error;
1472 }
1473
1474 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001475 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001476 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1477 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001478 goto error;
1479 }
1480
1481 GETVAL(value, child, "value");
1482 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001483 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001484 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001485 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001487 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001488 goto error;
1489 }
1490
1491 if (d->mod == LY_DEVIATE_ADD) {
1492 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001493 if (dev_target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001494 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1495 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001496 goto error;
1497 }
1498 }
1499
1500 if (d->mod == LY_DEVIATE_DEL) {
1501 /* check values */
Michal Vasko60f4b452016-02-12 11:02:55 +01001502 if ((d->flags & LYS_MAND_MASK) != (dev_target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001503 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1504 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001505 goto error;
1506 }
1507 /* remove current mandatory value of the target */
Michal Vasko60f4b452016-02-12 11:02:55 +01001508 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001509 } else { /* add (already checked) and replace */
1510 /* remove current mandatory value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001511 dev_target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001512
1513 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001514 dev_target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001515 }
1516 } else if (!strcmp(child->name, "min-elements")) {
1517 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001518 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 goto error;
1520 }
1521 f_min = 1;
1522
Michal Vasko60f4b452016-02-12 11:02:55 +01001523 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001524 goto error;
1525 }
1526 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001527 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001528 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001529 goto error;
1530 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001531 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001532
Michal Vasko60f4b452016-02-12 11:02:55 +01001533 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001534 goto error;
1535 }
1536 } else if (!strcmp(child->name, "must")) {
1537 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001538 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001539 continue;
1540 } else if (!strcmp(child->name, "type")) {
1541 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001542 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 goto error;
1544 }
1545
1546 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001547 if (dev_target->nodetype == LYS_LEAF) {
1548 t = &((struct lys_node_leaf *)dev_target)->type;
1549 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1550 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001551 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001552 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1553 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 goto error;
1555 }
1556
1557 if (d->mod == LY_DEVIATE_ADD) {
1558 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001559 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1560 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001561 goto error;
1562 } else if (d->mod == LY_DEVIATE_DEL) {
1563 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001564 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1565 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 goto error;
1567 }
1568
1569 /* replace */
1570 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001571 lys_type_free(ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001572
1573 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001574 /* HACK for unres */
1575 t->der = (struct lys_tpdf *)child;
Michal Vasko60f4b452016-02-12 11:02:55 +01001576 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001577 goto error;
1578 }
1579 d->type = t;
1580 } else if (!strcmp(child->name, "unique")) {
1581 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001582 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001583 continue;
1584 } else if (!strcmp(child->name, "units")) {
1585 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001586 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 goto error;
1588 }
1589
1590 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001591 if (dev_target->nodetype == LYS_LEAFLIST) {
1592 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1593 } else if (dev_target->nodetype == LYS_LEAF) {
1594 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001595 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001596 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1597 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001598 goto error;
1599 }
1600
1601 /* get units value */
1602 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001603 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001604
1605 /* apply to target */
1606 if (d->mod == LY_DEVIATE_ADD) {
1607 /* check that there is no current value */
1608 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001609 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1610 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001611 goto error;
1612 }
1613 }
1614
1615 if (d->mod == LY_DEVIATE_DEL) {
1616 /* check values */
1617 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001618 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1619 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001620 goto error;
1621 }
1622 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001623 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001624 } else { /* add (already checked) and replace */
1625 /* remove current units value of the target ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001626 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001627
1628 /* ... and replace it with the value specified in deviation */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001629 *stritem = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001630 }
1631 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001632 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001633 goto error;
1634 }
1635
Michal Vasko88c29542015-11-27 14:57:53 +01001636 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 }
1638
1639 if (c_must) {
1640 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001641 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001642 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001643 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1644 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 break;
Radek Krejci76512572015-08-04 09:47:08 +02001646 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001647 trg_must = &((struct lys_node_container *)dev_target)->must;
1648 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001649 break;
Radek Krejci76512572015-08-04 09:47:08 +02001650 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001651 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1652 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 break;
Radek Krejci76512572015-08-04 09:47:08 +02001654 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001655 trg_must = &((struct lys_node_list *)dev_target)->must;
1656 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001657 break;
Radek Krejci76512572015-08-04 09:47:08 +02001658 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001659 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1660 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001661 break;
1662 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001663 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1664 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 goto error;
1666 }
1667
1668 if (d->mod == LY_DEVIATE_RPL) {
1669 /* remove target's musts and allocate new array for it */
1670 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001671 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1672 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001673 goto error;
1674 }
1675
1676 for (i = 0; i < list->must_size; i++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001677 lys_restr_free(ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001678 }
1679 free(*trg_must);
1680 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1681 d->must_size = c_must;
1682 *trg_must_size = 0;
1683 } else if (d->mod == LY_DEVIATE_ADD) {
1684 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001685 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001686 if (!d->must) {
1687 LOGMEM;
1688 goto error;
1689 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001690 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001691 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 d->must_size = c_must;
1693 } else { /* LY_DEVIATE_DEL */
1694 d->must = calloc(c_must, sizeof *d->must);
1695 }
Michal Vasko253035f2015-12-17 16:58:13 +01001696 if (!d->must) {
1697 LOGMEM;
1698 goto error;
1699 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001700 }
1701 if (c_uniq) {
1702 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001703 if (dev_target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001704 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1705 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001706 goto error;
1707 }
1708
Michal Vasko60f4b452016-02-12 11:02:55 +01001709 list = (struct lys_node_list *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001710 if (d->mod == LY_DEVIATE_RPL) {
1711 /* remove target's unique and allocate new array for it */
1712 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001713 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1714 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001715 goto error;
1716 }
1717
1718 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001719 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001720 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001721 }
1722 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001723 }
1724 free(list->unique);
1725 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1726 d->unique_size = c_uniq;
1727 list->unique_size = 0;
1728 } else if (d->mod == LY_DEVIATE_ADD) {
1729 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001730 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001731 list->unique = d->unique;
1732 d->unique = &list->unique[list->unique_size];
1733 d->unique_size = c_uniq;
1734 } else { /* LY_DEVIATE_DEL */
1735 d->unique = calloc(c_uniq, sizeof *d->unique);
1736 }
Michal Vasko253035f2015-12-17 16:58:13 +01001737 if (!d->unique) {
1738 LOGMEM;
1739 goto error;
1740 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 }
1742
1743 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001744 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001745 if (!strcmp(child->name, "must")) {
1746 if (d->mod == LY_DEVIATE_DEL) {
1747 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1748 goto error;
1749 }
1750
1751 /* find must to delete, we are ok with just matching conditions */
1752 for (i = 0; i < *trg_must_size; i++) {
1753 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1754 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001755 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 /* ... and maintain the array */
1757 (*trg_must_size)--;
1758 if (i != *trg_must_size) {
1759 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1760 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1761 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1762 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1763 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1764 }
1765 if (!(*trg_must_size)) {
1766 free(*trg_must);
1767 *trg_must = NULL;
1768 } else {
1769 (*trg_must)[*trg_must_size].expr = NULL;
1770 (*trg_must)[*trg_must_size].dsc = NULL;
1771 (*trg_must)[*trg_must_size].ref = NULL;
1772 (*trg_must)[*trg_must_size].eapptag = NULL;
1773 (*trg_must)[*trg_must_size].emsg = NULL;
1774 }
1775
1776 i = -1; /* set match flag */
1777 break;
1778 }
1779 }
1780 d->must_size++;
1781 if (i != -1) {
1782 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001783 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1784 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001785 goto error;
1786 }
1787 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001788 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1789 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 goto error;
1791 }
1792 (*trg_must_size)++;
1793 }
1794 } else if (!strcmp(child->name, "unique")) {
1795 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001796 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001797 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 goto error;
1799 }
1800
1801 /* find unique structures to delete */
1802 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001803 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001804 continue;
1805 }
1806
Radek Krejci581ce772015-11-10 17:22:40 +01001807 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1808 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001809 break;
1810 }
1811 }
1812
Radek Krejci581ce772015-11-10 17:22:40 +01001813 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001815 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001816 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001817 }
1818 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001819 /* ... and maintain the array */
1820 list->unique_size--;
1821 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001822 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1823 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 }
1825
1826 if (!list->unique_size) {
1827 free(list->unique);
1828 list->unique = NULL;
1829 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001830 list->unique[list->unique_size].expr_size = 0;
1831 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001832 }
1833
1834 i = -1; /* set match flag */
1835 break;
1836 }
1837 }
1838
1839 d->unique_size++;
1840 if (i != -1) {
1841 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001842 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1843 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 goto error;
1845 }
1846 } else { /* replace or add */
Michal Vasko60f4b452016-02-12 11:02:55 +01001847 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001848 list->unique_size++;
1849 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001850 goto error;
1851 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 }
1853 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001854 }
Radek Krejci5b917642015-07-02 09:03:13 +02001855
1856 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 }
1858
Radek Krejcieb00f512015-07-01 16:44:58 +02001859 return EXIT_SUCCESS;
1860
1861error:
1862
Radek Krejcieb00f512015-07-01 16:44:58 +02001863 return EXIT_FAILURE;
1864}
1865
Michal Vasko0d343d12015-08-24 14:57:36 +02001866/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001867static int
Radek Krejcib8048692015-08-05 13:36:34 +02001868fill_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 +02001869 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001870{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001872 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001873 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001874 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001875
Michal Vasko591e0b22015-08-13 13:53:43 +02001876 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001878 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001879 if (!aug->target_name) {
1880 goto error;
1881 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001882 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001883
Michal Vasko1d87a922015-08-21 12:57:16 +02001884 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001885 goto error;
1886 }
1887
1888 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001889 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1890 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001891 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001892 continue;
1893 }
1894
Radek Krejci3cf9e222015-06-18 11:37:50 +02001895 if (!strcmp(child->name, "if-feature")) {
1896 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001897 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001898 } else if (!strcmp(child->name, "when")) {
1899 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001900 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001901 goto error;
1902 }
1903
1904 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001905 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001906 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001907 goto error;
1908 }
Michal Vaskofcdac172015-10-07 09:35:05 +02001909 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001910 goto error;
1911 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001912 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001913 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001914
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001915 /* check allowed data sub-statements */
1916 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001917 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001918 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001919 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001920 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001921 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001923 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001924 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001925 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001926 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001927 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001928 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001929 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001930 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001931 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001932 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001933 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001934 goto error;
1935 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001936
Radek Krejci1d82ef62015-08-07 14:44:40 +02001937 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001938 goto error;
1939 }
1940
1941 /* check for mandatory nodes - if the target node is in another module
1942 * the added nodes cannot be mandatory
1943 */
Radek Krejcic6556022016-01-27 15:16:45 +01001944 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001945 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001946 goto error;
1947 }
1948
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001950 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001951 }
1952
1953 if (c) {
1954 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001955 if (!aug->features) {
1956 LOGMEM;
1957 goto error;
1958 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001959 }
1960
1961 LY_TREE_FOR_SAFE(yin->child, next, child) {
1962 if (!strcmp(child->name, "if-feature")) {
1963 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001964 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001965 goto error;
1966 }
Michal Vasko7178e692016-02-12 15:58:05 +01001967 /* HACK - store pointer to the parent node for later status check */
Radek Krejcicf509982015-12-15 09:22:44 +01001968 aug->features[aug->features_size] = (struct lys_feature *)aug;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001969 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001970 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001971 aug->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001972 lydict_remove(module->ctx, value);
1973 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001974 goto error;
1975 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001976 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001977 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001978 }
1979
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02001981 * connected to the tree and adjusted (if possible right now).
1982 * However, if this is augment in a uses, it gets resolved
1983 * when the uses does and cannot be resolved now for sure
1984 * (the grouping was not yet copied into uses).
1985 */
1986 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko7178e692016-02-12 15:58:05 +01001987 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin)) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02001988 goto error;
1989 }
Michal Vasko49291b32015-08-06 09:49:41 +02001990 }
Radek Krejci106efc02015-06-10 14:36:27 +02001991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02001993
1994error:
1995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02001997}
1998
Michal Vasko0d343d12015-08-24 14:57:36 +02001999/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000static int
Michal Vasko0d204592015-10-07 09:50:04 +02002001fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002002{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 struct lyxml_elem *sub, *next;
2004 const char *value;
2005 char *endptr;
2006 int f_mand = 0, f_min = 0, f_max = 0;
2007 int c_must = 0;
2008 int r;
2009 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002010
Radek Krejci76512572015-08-04 09:47:08 +02002011 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 goto error;
2013 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002015 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002016 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002017 if (!rfn->target_name) {
2018 goto error;
2019 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002022 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2023 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002024 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002025 continue;
2026 }
2027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 /* limited applicability */
2029 if (!strcmp(sub->name, "default")) {
2030 /* leaf or choice */
2031 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002032 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 goto error;
2034 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 /* check possibility of statements combination */
2037 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002038 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002040 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 goto error;
2042 }
2043 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002044 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 GETVAL(value, sub, "value");
2048 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2049 } else if (!strcmp(sub->name, "mandatory")) {
2050 /* leaf, choice or anyxml */
2051 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002052 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002053 goto error;
2054 }
2055 /* just checking the flags in leaf is not sufficient, we would allow
2056 * multiple mandatory statements with the "false" value
2057 */
2058 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 /* check possibility of statements combination */
2061 if (rfn->target_type) {
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 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002064 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 goto error;
2066 }
2067 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002068 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 GETVAL(value, sub, "value");
2072 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002073 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002075 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002077 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 goto error;
2079 }
2080 } else if (!strcmp(sub->name, "min-elements")) {
2081 /* list or leaf-list */
2082 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002083 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 goto error;
2085 }
2086 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 /* check possibility of statements combination */
2089 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002090 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002092 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 goto error;
2094 }
2095 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002096 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 GETVAL(value, sub, "value");
2100 while (isspace(value[0])) {
2101 value++;
2102 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 /* convert it to uint32_t */
2105 errno = 0;
2106 endptr = NULL;
2107 val = strtoul(value, &endptr, 10);
2108 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002109 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 goto error;
2111 }
2112 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 /* magic - bit 3 in flags means min set */
2115 rfn->flags |= 0x04;
2116 } else if (!strcmp(sub->name, "max-elements")) {
2117 /* list or leaf-list */
2118 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002119 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 goto error;
2121 }
2122 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 /* check possibility of statements combination */
2125 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002126 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002128 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 goto error;
2130 }
2131 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002132 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 GETVAL(value, sub, "value");
2136 while (isspace(value[0])) {
2137 value++;
2138 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002139
Radek Krejci0d7b2472016-02-12 11:11:03 +01002140 if (!strcmp(value, "unbounded")) {
2141 rfn->mod.list.max = 0;
2142 } else {
2143 /* convert it to uint32_t */
2144 errno = 0;
2145 endptr = NULL;
2146 val = strtoul(value, &endptr, 10);
2147 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
2148 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
2149 goto error;
2150 }
2151 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 /* magic - bit 4 in flags means min set */
2155 rfn->flags |= 0x08;
2156 } else if (!strcmp(sub->name, "presence")) {
2157 /* container */
2158 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002159 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 goto error;
2161 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 /* check possibility of statements combination */
2164 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002165 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002167 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 goto error;
2169 }
2170 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002171 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 GETVAL(value, sub, "value");
2175 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2176 } else if (!strcmp(sub->name, "must")) {
2177 /* leaf-list, list, container or anyxml */
2178 /* check possibility of statements combination */
2179 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002180 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002182 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 goto error;
2184 }
2185 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002186 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002190 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002193 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 goto error;
2195 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002196
Michal Vasko345da0a2015-12-02 10:35:55 +01002197 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 /* process nodes with cardinality of 0..n */
2201 if (c_must) {
2202 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002203 if (!rfn->must) {
2204 LOGMEM;
2205 goto error;
2206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 }
Radek Krejci73adb602015-07-02 18:07:40 +02002208 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002209 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2210 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002211 if (r) {
2212 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 }
Michal Vasko0d204592015-10-07 09:50:04 +02002214 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002215 goto error;
2216 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002220
2221error:
2222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002224}
2225
Michal Vasko0d343d12015-08-24 14:57:36 +02002226/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227static int
Radek Krejcib8048692015-08-05 13:36:34 +02002228fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002229{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 struct lyxml_elem *child;
2231 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002232 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002235 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2236 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002237 continue;
2238 }
2239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 if (!strcmp(child->name, "prefix")) {
2241 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002242 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 goto error;
2244 }
2245 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2246 } else if (!strcmp(child->name, "revision-date")) {
2247 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002248 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 goto error;
2250 }
2251 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002252 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 goto error;
2254 }
2255 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2256 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002257 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 goto error;
2259 }
2260 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 /* check mandatory information */
2263 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002264 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 goto error;
2266 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002269
2270 /* check for circular import, store it if passed */
2271 if (!module->ctx->models.parsing) {
2272 count = 0;
2273 } else {
2274 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2275 if (value == module->ctx->models.parsing[count]) {
2276 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2277 goto error;
2278 }
2279 }
2280 }
2281 ++count;
2282 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002283 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2284 if (!module->ctx->models.parsing) {
2285 LOGMEM;
2286 goto error;
2287 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002288 module->ctx->models.parsing[count - 1] = value;
2289 module->ctx->models.parsing[count] = NULL;
2290
2291 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002292 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 +02002293 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002294 /* whether to use a user callback is decided in the function */
2295 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 +02002296 }
2297
2298 /* remove the new module name now that its parsing is finished (even if failed) */
2299 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2300 LOGINT;
2301 }
2302 --count;
2303 if (count) {
2304 module->ctx->models.parsing[count] = NULL;
2305 } else {
2306 free(module->ctx->models.parsing);
2307 module->ctx->models.parsing = NULL;
2308 }
2309
2310 /* check the result */
2311 if (!imp->module) {
2312 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2313 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2314 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002318
2319error:
2320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002322}
2323
Michal Vasko0d343d12015-08-24 14:57:36 +02002324/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002326fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2327 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002328{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 struct lyxml_elem *child;
2330 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002331 char *module_data;
2332 void (*module_data_free)(char *module_data) = NULL;
2333 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002334 int count, i;
Radek Krejciefaeba32015-05-27 14:30:57 +02002335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002336 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002337 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2338 /* garbage */
2339 continue;
2340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 if (!strcmp(child->name, "revision-date")) {
2342 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002343 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 goto error;
2345 }
2346 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002347 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 goto error;
2349 }
2350 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2351 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002352 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002353 goto error;
2354 }
2355 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002358
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002359 /* check that the submodule was not included yet (previous submodule could have included it) */
2360 for (i = 0; i < module->inc_size; ++i) {
2361 if (module->inc[i].submodule && (module->inc[i].submodule->name == value)) {
Michal Vasko5ff78822016-02-12 09:33:31 +01002362 /* copy the duplicate into the result */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002363 memcpy(inc, &module->inc[i], sizeof *inc);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002364
Michal Vasko5ff78822016-02-12 09:33:31 +01002365 if (submodule) {
2366 /* we don't care if it was external or not */
2367 inc->external = 0;
2368 } else if (inc->external) {
2369 /* remove the duplicate */
2370 --module->inc_size;
2371 memmove(&module->inc[i], &module->inc[i + 1], (module->inc_size - i) * sizeof *inc);
2372 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
2373
2374 /* it is no longer external */
2375 inc->external = 0;
2376 }
2377 /* if !submodule && !inc->external, we just create a duplicate so it is detected and ended with error */
Michal Vasko9c4c99d2016-02-11 15:47:08 +01002378
2379 return EXIT_SUCCESS;
2380 }
2381 }
2382
Michal Vasko1b882eb2015-10-22 11:43:14 +02002383 /* check for circular include, store it if passed */
2384 if (!module->ctx->models.parsing) {
2385 count = 0;
2386 } else {
2387 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2388 if (value == module->ctx->models.parsing[count]) {
2389 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2390 goto error;
2391 }
2392 }
2393 }
2394 ++count;
2395 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002396 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2397 if (!module->ctx->models.parsing) {
2398 LOGMEM;
2399 goto error;
2400 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002401 module->ctx->models.parsing[count - 1] = value;
2402 module->ctx->models.parsing[count] = NULL;
2403
2404 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002405 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002407 if (module->ctx->module_clb) {
2408 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2409 &format, &module_data_free);
2410 if (module_data) {
Radek Krejcic071c542016-01-27 14:57:51 +01002411 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002412 if (module_data_free) {
2413 module_data_free(module_data);
2414 } else {
2415 free(module_data);
2416 }
2417 } else {
2418 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2419 }
2420 } else {
2421 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
Radek Krejcic071c542016-01-27 14:57:51 +01002422 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002423 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002424 }
2425
2426 /* remove the new submodule name now that its parsing is finished (even if failed) */
2427 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2428 LOGINT;
2429 }
2430 --count;
2431 if (count) {
2432 module->ctx->models.parsing[count] = NULL;
2433 } else {
2434 free(module->ctx->models.parsing);
2435 module->ctx->models.parsing = NULL;
2436 }
2437
2438 /* check the result */
2439 if (!inc->submodule) {
2440 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2441 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002443 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002446
2447error:
2448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002450}
2451
Michal Vasko0d343d12015-08-24 14:57:36 +02002452/* logs directly
2453 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002454 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002455 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002456 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002457 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458static int
Radek Krejcib8048692015-08-05 13:36:34 +02002459read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002460 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002461{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 const char *value;
2463 struct lyxml_elem *sub, *next;
2464 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002467 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002468 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 if (opt & OPT_IDENT) {
2471 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002472 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 goto error;
2474 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002475 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002477
Radek Krejci6764bb32015-07-03 15:16:04 +02002478 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002479 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002480 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002481 }
2482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 /* process local parameters */
2484 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002485 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002486 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002487 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002488 continue;
2489 }
2490 if (strcmp(sub->ns->value, LY_NSYIN)) {
2491 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002492 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002493 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002494 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002495 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002496 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002497 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002498 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002499 goto error;
2500 }
2501 }
2502
2503 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002504 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002505 continue;
2506 }
2507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002509 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002510 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 goto error;
2512 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002513 node->dsc = read_yin_subnode(ctx, sub, "text");
2514 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002515 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002516 }
2517 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002518 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002519 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 goto error;
2521 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002522 node->ref = read_yin_subnode(ctx, sub, "text");
2523 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002524 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 }
2526 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002527 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002528 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 goto error;
2530 }
2531 GETVAL(value, sub, "value");
2532 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002533 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002535 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002536 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002537 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002539 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002540 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 }
2542 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002543 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002544 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 goto error;
2546 }
2547 GETVAL(value, sub, "value");
2548 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002549 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002551 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002553 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002554 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 }
2556 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002557 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002558 continue;
2559 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002560 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002561 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002562
Radek Krejci1d82ef62015-08-07 14:44:40 +02002563 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 /* get config flag from parent */
2565 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002566 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 } else {
2568 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002569 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002570 }
2571 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002574
2575error:
2576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002578}
2579
Michal Vasko0d343d12015-08-24 14:57:36 +02002580/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002581static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002582read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002583{
Radek Krejci76512572015-08-04 09:47:08 +02002584 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002585 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002586 const char *value;
2587
2588 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002589 if (!retval) {
2590 LOGMEM;
2591 return NULL;
2592 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002593
2594 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002595 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002596 if (!retval->cond) {
2597 goto error;
2598 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002599
Radek Krejci73adb602015-07-02 18:07:40 +02002600 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002601 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2602 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002603 continue;
2604 }
2605
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002606 if (!strcmp(child->name, "description")) {
2607 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002608 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002609 goto error;
2610 }
2611 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2612 if (!retval->dsc) {
2613 goto error;
2614 }
2615 } else if (!strcmp(child->name, "reference")) {
2616 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002617 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002618 goto error;
2619 }
2620 retval->ref = read_yin_subnode(module->ctx, child, "text");
2621 if (!retval->ref) {
2622 goto error;
2623 }
2624 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002625 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002626 goto error;
2627 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002628 }
2629
2630 return retval;
2631
2632error:
2633
Michal Vasko0308dd62015-10-07 09:14:40 +02002634 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002635 return NULL;
2636}
2637
Michal Vasko0d343d12015-08-24 14:57:36 +02002638/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002639static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002640read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2641 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002642{
Michal Vasko29fc0182015-08-24 15:02:39 +02002643 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002644 struct lys_node_case *cs;
2645 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002646 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002647 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002648
Radek Krejcie867c852015-08-27 09:52:34 +02002649 /* init */
2650 memset(&root, 0, sizeof root);
2651
Radek Krejci1d82ef62015-08-07 14:44:40 +02002652 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002653 if (!cs) {
2654 LOGMEM;
2655 return NULL;
2656 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002657 cs->nodetype = LYS_CASE;
2658 cs->prev = (struct lys_node *)cs;
2659 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002660
Radek Krejci6a113852015-07-03 16:04:20 +02002661 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002662 goto error;
2663 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002664
Radek Krejcia9544502015-08-14 08:24:29 +02002665 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2666
Michal Vasko3a0043f2015-08-12 12:11:30 +02002667 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002668 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002669 goto error;
2670 }
2671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002672 /* process choice's specific children */
2673 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002674 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2675 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002676 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002677 continue;
2678 }
2679
Michal Vasko29fc0182015-08-24 15:02:39 +02002680 if (!strcmp(sub->name, "container") ||
2681 !strcmp(sub->name, "leaf-list") ||
2682 !strcmp(sub->name, "leaf") ||
2683 !strcmp(sub->name, "list") ||
2684 !strcmp(sub->name, "uses") ||
2685 !strcmp(sub->name, "choice") ||
2686 !strcmp(sub->name, "anyxml")) {
2687
Michal Vaskof3930de2015-10-22 12:03:59 +02002688 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002689 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002690 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002691 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002692 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002693 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002694 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002695 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002696 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002697 goto error;
2698 }
2699
Radek Krejci1d82ef62015-08-07 14:44:40 +02002700 cs->when = read_yin_when(module, sub);
2701 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002702 goto error;
2703 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002704 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002705 goto error;
2706 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002707
Michal Vasko345da0a2015-12-02 10:35:55 +01002708 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002709 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002710 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002711 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002714
Radek Krejci3cf9e222015-06-18 11:37:50 +02002715 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002716 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002717 if (!cs->features) {
2718 LOGMEM;
2719 goto error;
2720 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002721 }
Radek Krejci73adb602015-07-02 18:07:40 +02002722 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002723 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002724 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002725 goto error;
2726 }
Radek Krejcicf509982015-12-15 09:22:44 +01002727 /* hack - store pointer to the parent node for later status check */
2728 cs->features[cs->features_size] = (struct lys_feature *)cs;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002729 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002730 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002731 cs->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002732 lydict_remove(module->ctx, value);
2733 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002734 goto error;
2735 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 }
Radek Krejcib388c152015-06-04 17:03:03 +02002737
Michal Vasko29fc0182015-08-24 15:02:39 +02002738 /* last part - process data nodes */
2739 LY_TREE_FOR_SAFE(root.child, next, sub) {
2740 if (!strcmp(sub->name, "container")) {
2741 node = read_yin_container(module, retval, sub, resolve, unres);
2742 } else if (!strcmp(sub->name, "leaf-list")) {
2743 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2744 } else if (!strcmp(sub->name, "leaf")) {
2745 node = read_yin_leaf(module, retval, sub, resolve, unres);
2746 } else if (!strcmp(sub->name, "list")) {
2747 node = read_yin_list(module, retval, sub, resolve, unres);
2748 } else if (!strcmp(sub->name, "choice")) {
2749 node = read_yin_choice(module, retval, sub, resolve, unres);
2750 } else if (!strcmp(sub->name, "uses")) {
2751 node = read_yin_uses(module, retval, sub, resolve, unres);
2752 } else if (!strcmp(sub->name, "anyxml")) {
2753 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2754 }
2755 if (!node) {
2756 goto error;
2757 }
2758
Michal Vasko345da0a2015-12-02 10:35:55 +01002759 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002760 }
2761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002762 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002763
2764error:
2765
Michal Vasko29fc0182015-08-24 15:02:39 +02002766 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002767 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002768 }
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002769 lys_node_free(retval, NULL);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002772}
2773
Michal Vasko0d343d12015-08-24 14:57:36 +02002774/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002775static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002776read_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 +02002777{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002778 struct lyxml_elem *sub, *next;
2779 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002780 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002781 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002782 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002783 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002786 if (!choice) {
2787 LOGMEM;
2788 return NULL;
2789 }
Radek Krejci76512572015-08-04 09:47:08 +02002790 choice->nodetype = LYS_CHOICE;
2791 choice->prev = (struct lys_node *)choice;
2792 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002793
Michal Vaskoe0c59842015-09-24 13:52:20 +02002794 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2795 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002796 goto error;
2797 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002798
Radek Krejcia9544502015-08-14 08:24:29 +02002799 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2800
Michal Vasko3a0043f2015-08-12 12:11:30 +02002801 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002802 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002803 goto error;
2804 }
2805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002806 /* process choice's specific children */
2807 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002808 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2809 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002810 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002811 continue;
2812 }
2813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002815 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 goto error;
2817 }
2818 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002819 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002820 goto error;
2821 }
2822 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002823 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002824 goto error;
2825 }
2826 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002827 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002828 goto error;
2829 }
2830 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002831 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 goto error;
2833 }
2834 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002835 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 goto error;
2837 }
2838 } else if (!strcmp(sub->name, "default")) {
2839 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002840 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 goto error;
2842 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002843 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 } else if (!strcmp(sub->name, "mandatory")) {
2845 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002846 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002847 goto error;
2848 }
2849 /* just checking the flags in leaf is not sufficient, we would allow
2850 * multiple mandatory statements with the "false" value
2851 */
2852 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002854 GETVAL(value, sub, "value");
2855 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002856 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002857 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002858 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002859 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002860 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 goto error;
2862 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002863 } else if (!strcmp(sub->name, "when")) {
2864 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002865 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002866 goto error;
2867 }
2868
2869 choice->when = read_yin_when(module, sub);
2870 if (!choice->when) {
2871 goto error;
2872 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002873 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002874 goto error;
2875 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002876 } else if (!strcmp(sub->name, "if-feature")) {
2877 c_ftrs++;
2878
Michal Vasko345da0a2015-12-02 10:35:55 +01002879 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002880 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002882 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002885
Radek Krejci1d82ef62015-08-07 14:44:40 +02002886 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002887 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002889
Radek Krejci3cf9e222015-06-18 11:37:50 +02002890 if (c_ftrs) {
2891 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002892 if (!choice->features) {
2893 LOGMEM;
2894 goto error;
2895 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002896 }
2897
Radek Krejci73adb602015-07-02 18:07:40 +02002898 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002899 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002900 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002901 goto error;
2902 }
Radek Krejcicf509982015-12-15 09:22:44 +01002903 /* hack - store pointer to the parent node for later status check */
2904 choice->features[choice->features_size] = (struct lys_feature *)choice;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002905 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002906 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002907 choice->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002908 lydict_remove(module->ctx, value);
2909 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002910 goto error;
2911 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002912 }
2913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002915 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002916 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2918 goto error;
2919 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 /* link default with the case */
2922 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002923 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002924 goto error;
2925 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002928 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002929
2930error:
2931
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002932 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002935}
2936
Michal Vasko0d343d12015-08-24 14:57:36 +02002937/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002938static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002939read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002940 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002941{
Radek Krejci76512572015-08-04 09:47:08 +02002942 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002943 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 struct lyxml_elem *sub, *next;
2945 const char *value;
2946 int r;
2947 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002948 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002951 if (!anyxml) {
2952 LOGMEM;
2953 return NULL;
2954 }
Radek Krejci76512572015-08-04 09:47:08 +02002955 anyxml->nodetype = LYS_ANYXML;
2956 anyxml->prev = (struct lys_node *)anyxml;
2957 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002958
Michal Vaskoe0c59842015-09-24 13:52:20 +02002959 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2960 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 goto error;
2962 }
Radek Krejci863c2852015-06-03 15:47:11 +02002963
Radek Krejcia9544502015-08-14 08:24:29 +02002964 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002965
Radek Krejcic071c542016-01-27 14:57:51 +01002966 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002967 goto error;
2968 }
2969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002970 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002971 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2972 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002973 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002974 continue;
2975 }
2976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 if (!strcmp(sub->name, "mandatory")) {
2978 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002979 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 goto error;
2981 }
2982 /* just checking the flags in leaf is not sufficient, we would allow
2983 * multiple mandatory statements with the "false" value
2984 */
2985 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 GETVAL(value, sub, "value");
2988 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002989 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002990 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002991 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002992 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002993 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 goto error;
2995 }
2996 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002997 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002998 } else if (!strcmp(sub->name, "when")) {
2999 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003000 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003001 goto error;
3002 }
3003
3004 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003005 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003006 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003007 goto error;
3008 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003009 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003010 goto error;
3011 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003012 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 } else if (!strcmp(sub->name, "must")) {
3014 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003015 } else if (!strcmp(sub->name, "if-feature")) {
3016 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003019 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 }
3022 }
Radek Krejci863c2852015-06-03 15:47:11 +02003023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 /* middle part - process nodes with cardinality of 0..n */
3025 if (c_must) {
3026 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003027 if (!anyxml->must) {
3028 LOGMEM;
3029 goto error;
3030 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003032 if (c_ftrs) {
3033 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003034 if (!anyxml->features) {
3035 LOGMEM;
3036 goto error;
3037 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003038 }
Radek Krejci863c2852015-06-03 15:47:11 +02003039
Radek Krejci73adb602015-07-02 18:07:40 +02003040 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003042 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3043 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 if (r) {
3045 goto error;
3046 }
Michal Vasko0d204592015-10-07 09:50:04 +02003047 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003048 goto error;
3049 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003050 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003051 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003052 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003053 goto error;
3054 }
Radek Krejcicf509982015-12-15 09:22:44 +01003055 /* hack - store pointer to the parent node for later status check */
3056 anyxml->features[anyxml->features_size] = (struct lys_feature *)anyxml;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003057 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003058 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003059 anyxml->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003060 lydict_remove(module->ctx, value);
3061 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003062 goto error;
3063 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 }
Radek Krejci863c2852015-06-03 15:47:11 +02003066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003068
3069error:
3070
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003071 lys_node_free(retval, NULL);
Radek Krejci863c2852015-06-03 15:47:11 +02003072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003074}
3075
Michal Vasko0d343d12015-08-24 14:57:36 +02003076/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003077static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003078read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003079 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003080{
Radek Krejci76512572015-08-04 09:47:08 +02003081 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003082 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 struct lyxml_elem *sub, *next;
3084 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003085 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003086 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003089 if (!leaf) {
3090 LOGMEM;
3091 return NULL;
3092 }
Radek Krejci76512572015-08-04 09:47:08 +02003093 leaf->nodetype = LYS_LEAF;
3094 leaf->prev = (struct lys_node *)leaf;
3095 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003096
Michal Vaskoe0c59842015-09-24 13:52:20 +02003097 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3098 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 goto error;
3100 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003101
Radek Krejcia9544502015-08-14 08:24:29 +02003102 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003103
Radek Krejcic071c542016-01-27 14:57:51 +01003104 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003105 goto error;
3106 }
3107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003108 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003109 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3110 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003111 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003112 continue;
3113 }
3114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003116 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003117 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 goto error;
3119 }
Michal Vasko88c29542015-11-27 14:57:53 +01003120 /* HACK for unres */
3121 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003122 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003123 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3124 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003127 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003128 } else if (!strcmp(sub->name, "default")) {
3129 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003130 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003131 goto error;
3132 }
3133 GETVAL(value, sub, "value");
3134 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003135 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 } else if (!strcmp(sub->name, "units")) {
3137 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003138 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 goto error;
3140 }
3141 GETVAL(value, sub, "name");
3142 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3143 } else if (!strcmp(sub->name, "mandatory")) {
3144 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003145 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003146 goto error;
3147 }
3148 /* just checking the flags in leaf is not sufficient, we would allow
3149 * multiple mandatory statements with the "false" value
3150 */
3151 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 GETVAL(value, sub, "value");
3154 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003155 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003156 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003157 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003158 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003159 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 goto error;
3161 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003162 } else if (!strcmp(sub->name, "when")) {
3163 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003164 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003165 goto error;
3166 }
3167
3168 leaf->when = read_yin_when(module, sub);
3169 if (!leaf->when) {
3170 goto error;
3171 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003172 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003173 goto error;
3174 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003177 c_must++;
3178 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003179 } else if (!strcmp(sub->name, "if-feature")) {
3180 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003184 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003187
Michal Vasko88c29542015-11-27 14:57:53 +01003188 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003189 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003192 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003193 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 goto error;
3195 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003196 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003197 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003198 goto error;
3199 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 /* middle part - process nodes with cardinality of 0..n */
3203 if (c_must) {
3204 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003205 if (!leaf->must) {
3206 LOGMEM;
3207 goto error;
3208 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003209 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003210 if (c_ftrs) {
3211 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003212 if (!leaf->features) {
3213 LOGMEM;
3214 goto error;
3215 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003216 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003217
Radek Krejci73adb602015-07-02 18:07:40 +02003218 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003220 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3221 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 if (r) {
3223 goto error;
3224 }
Michal Vasko0d204592015-10-07 09:50:04 +02003225 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003226 goto error;
3227 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003228 } else if (!strcmp(sub->name, "if-feature")) {
3229 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003230 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003231 goto error;
3232 }
Radek Krejcicf509982015-12-15 09:22:44 +01003233 /* hack - store pointer to the parent node for later status check */
3234 leaf->features[leaf->features_size] = (struct lys_feature *)leaf;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003235 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003236 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003237 leaf->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003238 lydict_remove(module->ctx, value);
3239 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003240 goto error;
3241 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003242 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003246
3247error:
3248
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003249 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003252}
3253
Michal Vasko0d343d12015-08-24 14:57:36 +02003254/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003255static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003256read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003257 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003258{
Radek Krejci76512572015-08-04 09:47:08 +02003259 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003260 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 struct lyxml_elem *sub, *next;
3262 const char *value;
3263 char *endptr;
3264 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003265 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003266 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003270 if (!llist) {
3271 LOGMEM;
3272 return NULL;
3273 }
Radek Krejci76512572015-08-04 09:47:08 +02003274 llist->nodetype = LYS_LEAFLIST;
3275 llist->prev = (struct lys_node *)llist;
3276 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003277
Michal Vaskoe0c59842015-09-24 13:52:20 +02003278 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3279 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 goto error;
3281 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003282
Radek Krejcia9544502015-08-14 08:24:29 +02003283 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003284
Radek Krejcic071c542016-01-27 14:57:51 +01003285 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003286 goto error;
3287 }
3288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003290 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3291 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003292 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003293 continue;
3294 }
3295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003297 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003298 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 goto error;
3300 }
Michal Vasko88c29542015-11-27 14:57:53 +01003301 /* HACK for unres */
3302 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003303 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003304 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3305 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 goto error;
3307 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003308 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 } else if (!strcmp(sub->name, "units")) {
3310 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003311 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 goto error;
3313 }
3314 GETVAL(value, sub, "name");
3315 llist->units = lydict_insert(module->ctx, value, strlen(value));
3316 } else if (!strcmp(sub->name, "ordered-by")) {
3317 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003318 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 goto error;
3320 }
3321 /* just checking the flags in llist is not sufficient, we would
3322 * allow multiple ordered-by statements with the "system" value
3323 */
3324 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003325
Radek Krejci1574a8d2015-08-03 14:16:52 +02003326 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3328 * state data
3329 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003330 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 continue;
3332 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 GETVAL(value, sub, "value");
3335 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003336 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003338 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003340 } /* else system is the default value, so we can ignore it */
3341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 } else if (!strcmp(sub->name, "must")) {
3343 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003344 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003345 } else if (!strcmp(sub->name, "if-feature")) {
3346 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003347 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 } else if (!strcmp(sub->name, "min-elements")) {
3350 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003351 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
3354 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 GETVAL(value, sub, "value");
3357 while (isspace(value[0])) {
3358 value++;
3359 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 /* convert it to uint32_t */
3362 errno = 0;
3363 endptr = NULL;
3364 val = strtoul(value, &endptr, 10);
3365 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003366 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 goto error;
3368 }
3369 llist->min = (uint32_t) val;
3370 } else if (!strcmp(sub->name, "max-elements")) {
3371 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003372 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 goto error;
3374 }
3375 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003377 GETVAL(value, sub, "value");
3378 while (isspace(value[0])) {
3379 value++;
3380 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003381
Radek Krejci0d7b2472016-02-12 11:11:03 +01003382 if (!strcmp(value, "unbounded")) {
3383 llist->max = 0;
3384 } else {
3385 /* convert it to uint32_t */
3386 errno = 0;
3387 endptr = NULL;
3388 val = strtoul(value, &endptr, 10);
3389 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
3390 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
3391 goto error;
3392 }
3393 llist->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003394 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003395 } else if (!strcmp(sub->name, "when")) {
3396 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003397 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003398 goto error;
3399 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003400
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003401 llist->when = read_yin_when(module, sub);
3402 if (!llist->when) {
3403 goto error;
3404 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003405 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003406 goto error;
3407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003409 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003412
Michal Vasko88c29542015-11-27 14:57:53 +01003413 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003417 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003418 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 goto error;
3420 }
3421 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003422 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 goto error;
3424 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 /* middle part - process nodes with cardinality of 0..n */
3427 if (c_must) {
3428 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003429 if (!llist->must) {
3430 LOGMEM;
3431 goto error;
3432 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003434 if (c_ftrs) {
3435 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003436 if (!llist->features) {
3437 LOGMEM;
3438 goto error;
3439 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003440 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003441
Radek Krejci73adb602015-07-02 18:07:40 +02003442 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003444 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3445 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 if (r) {
3447 goto error;
3448 }
Michal Vasko0d204592015-10-07 09:50:04 +02003449 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003450 goto error;
3451 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003452 } else if (!strcmp(sub->name, "if-feature")) {
3453 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003454 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003455 goto error;
3456 }
Radek Krejcicf509982015-12-15 09:22:44 +01003457 /* hack - store pointer to the parent node for later status check */
3458 llist->features[llist->features_size] = (struct lys_feature *)llist;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003459 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003460 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003461 llist->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003462 lydict_remove(module->ctx, value);
3463 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003464 goto error;
3465 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003470
3471error:
3472
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003473 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003476}
3477
Michal Vasko0d343d12015-08-24 14:57:36 +02003478/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003479static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003480read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3481 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003482{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003483 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003484 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003486 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003487 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003489 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 char *auxs;
3491 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 /* init */
3494 memset(&root, 0, sizeof root);
3495 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003498 if (!list) {
3499 LOGMEM;
3500 return NULL;
3501 }
Radek Krejci76512572015-08-04 09:47:08 +02003502 list->nodetype = LYS_LIST;
3503 list->prev = (struct lys_node *)list;
3504 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003505
Michal Vaskoe0c59842015-09-24 13:52:20 +02003506 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3507 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 goto error;
3509 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003510
Radek Krejcia9544502015-08-14 08:24:29 +02003511 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 /* process list's specific children */
3514 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003515 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3516 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003517 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003518 continue;
3519 }
3520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 /* data statements */
3522 if (!strcmp(sub->name, "container") ||
3523 !strcmp(sub->name, "leaf-list") ||
3524 !strcmp(sub->name, "leaf") ||
3525 !strcmp(sub->name, "list") ||
3526 !strcmp(sub->name, "choice") ||
3527 !strcmp(sub->name, "uses") ||
3528 !strcmp(sub->name, "grouping") ||
3529 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003530 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003531 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 /* array counters */
3534 } else if (!strcmp(sub->name, "key")) {
3535 /* check cardinality 0..1 */
3536 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003537 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 goto error;
3539 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 /* count the number of keys */
3542 GETVAL(value, sub, "value");
3543 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003544 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 while ((value = strpbrk(value, " \t\n"))) {
3546 list->keys_size++;
3547 while (isspace(*value)) {
3548 value++;
3549 }
3550 }
3551 list->keys_size++;
3552 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003553 if (!list->keys) {
3554 LOGMEM;
3555 goto error;
3556 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 } else if (!strcmp(sub->name, "unique")) {
3558 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003559 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003560 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 } else if (!strcmp(sub->name, "typedef")) {
3562 c_tpdf++;
3563 } else if (!strcmp(sub->name, "must")) {
3564 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003565 } else if (!strcmp(sub->name, "if-feature")) {
3566 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 /* optional stetments */
3569 } else if (!strcmp(sub->name, "ordered-by")) {
3570 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003571 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 goto error;
3573 }
3574 /* just checking the flags in llist is not sufficient, we would
3575 * allow multiple ordered-by statements with the "system" value
3576 */
3577 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003578
Radek Krejci1574a8d2015-08-03 14:16:52 +02003579 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3581 * state data
3582 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003583 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 continue;
3585 }
Radek Krejci345ad742015-06-03 11:04:18 +02003586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 GETVAL(value, sub, "value");
3588 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003589 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003591 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003592 goto error;
3593 }
3594 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003595 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 } else if (!strcmp(sub->name, "min-elements")) {
3597 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003598 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 goto error;
3600 }
3601 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 GETVAL(value, sub, "value");
3604 while (isspace(value[0])) {
3605 value++;
3606 }
Radek Krejci345ad742015-06-03 11:04:18 +02003607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 /* convert it to uint32_t */
3609 errno = 0;
3610 auxs = NULL;
3611 val = strtoul(value, &auxs, 10);
3612 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003613 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 goto error;
3615 }
3616 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003617 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 } else if (!strcmp(sub->name, "max-elements")) {
3619 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003620 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 goto error;
3622 }
3623 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 GETVAL(value, sub, "value");
3626 while (isspace(value[0])) {
3627 value++;
3628 }
Radek Krejci345ad742015-06-03 11:04:18 +02003629
Radek Krejci0d7b2472016-02-12 11:11:03 +01003630 if (!strcmp(value, "unbounded")) {
3631 list->max = 0;;
3632 } else {
3633 /* convert it to uint32_t */
3634 errno = 0;
3635 auxs = NULL;
3636 val = strtoul(value, &auxs, 10);
3637 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
3638 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
3639 goto error;
3640 }
3641 list->max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003642 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003643 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003644 } else if (!strcmp(sub->name, "when")) {
3645 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003646 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003647 goto error;
3648 }
3649
3650 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003651 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003652 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003653 goto error;
3654 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003655 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003656 goto error;
3657 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003658 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003659 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003660 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003661 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003662 }
3663 }
Radek Krejci345ad742015-06-03 11:04:18 +02003664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003666 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003667 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 goto error;
3669 }
3670 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003671 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 goto error;
3673 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3676 if (c_tpdf) {
3677 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003678 if (!list->tpdf) {
3679 LOGMEM;
3680 goto error;
3681 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003683 if (c_must) {
3684 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003685 if (!list->must) {
3686 LOGMEM;
3687 goto error;
3688 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 }
3690 if (c_ftrs) {
3691 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003692 if (!list->features) {
3693 LOGMEM;
3694 goto error;
3695 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003696 }
Radek Krejci73adb602015-07-02 18:07:40 +02003697 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003699 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3700 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 if (r) {
3702 goto error;
3703 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003704 } else if (!strcmp(sub->name, "if-feature")) {
3705 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003706 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003707 goto error;
3708 }
Radek Krejcicf509982015-12-15 09:22:44 +01003709 /* hack - store pointer to the parent node for later status check */
3710 list->features[list->features_size] = (struct lys_feature *)list;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003711 r = unres_schema_add_str(module, unres, &list->features[list->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003712 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003713 list->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003714 lydict_remove(module->ctx, value);
3715 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003716 goto error;
3717 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003718 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003719 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3720 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003721 if (r) {
3722 goto error;
3723 }
Michal Vasko0d204592015-10-07 09:50:04 +02003724 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003725 goto error;
3726 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 }
3728 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003729
Radek Krejcic071c542016-01-27 14:57:51 +01003730 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003731 goto error;
3732 }
3733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 /* last part - process data nodes */
3735 LY_TREE_FOR_SAFE(root.child, next, sub) {
3736 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003737 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003739 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003741 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003743 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003745 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003747 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003749 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003750 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003751 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003752 } else {
3753 LOGINT;
3754 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003756 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757 goto error;
3758 }
Radek Krejci73adb602015-07-02 18:07:40 +02003759
Michal Vasko345da0a2015-12-02 10:35:55 +01003760 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003762
Radek Krejci461efb92016-02-12 15:52:18 +01003763 if (key_str) {
3764 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
3765 goto error;
3766 }
3767 } /* else config false list without a key, key_str presence in case of config true is checked earlier */
Radek Krejci812b10a2015-05-28 16:48:25 +02003768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 /* process unique statements */
3770 if (c_uniq) {
3771 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003772 if (!list->unique) {
3773 LOGMEM;
3774 goto error;
3775 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003776
Radek Krejci461efb92016-02-12 15:52:18 +01003777 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3778 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3779 list->unique_size++;
3780 if (r) {
3781 goto error;
3782 }
3783
3784 lyxml_free(module->ctx, sub);
3785 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003788 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003789
3790error:
3791
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003792 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003794 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 }
3796 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003797 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003801}
3802
Michal Vasko0d343d12015-08-24 14:57:36 +02003803/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003804static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003805read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3806 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003807{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003809 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003810 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003811 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 const char *value;
3813 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003814 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 /* init */
3817 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003820 if (!cont) {
3821 LOGMEM;
3822 return NULL;
3823 }
Radek Krejci76512572015-08-04 09:47:08 +02003824 cont->nodetype = LYS_CONTAINER;
3825 cont->prev = (struct lys_node *)cont;
3826 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003827
Michal Vaskoe0c59842015-09-24 13:52:20 +02003828 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3829 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 goto error;
3831 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003832
Radek Krejcia9544502015-08-14 08:24:29 +02003833 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 /* process container's specific children */
3836 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003837 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003838 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003839 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003840 continue;
3841 }
3842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 if (!strcmp(sub->name, "presence")) {
3844 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003845 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 goto error;
3847 }
3848 GETVAL(value, sub, "value");
3849 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003850
Michal Vasko345da0a2015-12-02 10:35:55 +01003851 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003852 } else if (!strcmp(sub->name, "when")) {
3853 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003854 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003855 goto error;
3856 }
3857
3858 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003859 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003860 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003861 goto error;
3862 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003863 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003864 goto error;
3865 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003866 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 /* data statements */
3869 } else if (!strcmp(sub->name, "container") ||
3870 !strcmp(sub->name, "leaf-list") ||
3871 !strcmp(sub->name, "leaf") ||
3872 !strcmp(sub->name, "list") ||
3873 !strcmp(sub->name, "choice") ||
3874 !strcmp(sub->name, "uses") ||
3875 !strcmp(sub->name, "grouping") ||
3876 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003877 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003878 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 /* array counters */
3881 } else if (!strcmp(sub->name, "typedef")) {
3882 c_tpdf++;
3883 } else if (!strcmp(sub->name, "must")) {
3884 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003885 } else if (!strcmp(sub->name, "if-feature")) {
3886 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003888 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003890 }
3891 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3894 if (c_tpdf) {
3895 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003896 if (!cont->tpdf) {
3897 LOGMEM;
3898 goto error;
3899 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 }
3901 if (c_must) {
3902 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003903 if (!cont->must) {
3904 LOGMEM;
3905 goto error;
3906 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003908 if (c_ftrs) {
3909 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003910 if (!cont->features) {
3911 LOGMEM;
3912 goto error;
3913 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003914 }
Radek Krejci800af702015-06-02 13:46:01 +02003915
Radek Krejci73adb602015-07-02 18:07:40 +02003916 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003918 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3919 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003920 if (r) {
3921 goto error;
3922 }
3923 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003924 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3925 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 if (r) {
3927 goto error;
3928 }
Michal Vasko0d204592015-10-07 09:50:04 +02003929 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003930 goto error;
3931 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003932 } else if (!strcmp(sub->name, "if-feature")) {
3933 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003934 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003935 goto error;
3936 }
Radek Krejcicf509982015-12-15 09:22:44 +01003937 /* hack - store pointer to the parent node for later status check */
3938 cont->features[cont->features_size] = (struct lys_feature *)cont;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003939 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003940 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003941 cont->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003942 lydict_remove(module->ctx, value);
3943 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003944 goto error;
3945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003948
Michal Vasko43b9d952016-02-15 11:07:03 +01003949 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto : module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003950 goto error;
3951 }
3952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 /* last part - process data nodes */
3954 LY_TREE_FOR_SAFE(root.child, next, sub) {
3955 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003958 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003964 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003966 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003967 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003970 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003972 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003973 goto error;
3974 }
Radek Krejci73adb602015-07-02 18:07:40 +02003975
Michal Vasko345da0a2015-12-02 10:35:55 +01003976 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003979 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003980
3981error:
3982
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003983 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003984 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003985 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003987
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003988 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003989}
3990
Michal Vasko0d343d12015-08-24 14:57:36 +02003991/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003992static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003993read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003994 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003995{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003997 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003998 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003999 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 int r;
4001 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 /* init */
4004 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004006 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004007 if (!grp) {
4008 LOGMEM;
4009 return NULL;
4010 }
Radek Krejci76512572015-08-04 09:47:08 +02004011 grp->nodetype = LYS_GROUPING;
4012 grp->prev = (struct lys_node *)grp;
4013 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004014
Michal Vasko71e1aa82015-08-12 12:17:51 +02004015 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004016 goto error;
4017 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004018
Radek Krejcia9544502015-08-14 08:24:29 +02004019 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4020
Radek Krejci1d82ef62015-08-07 14:44:40 +02004021 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004022 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4023 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004024 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004025 continue;
4026 }
4027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 /* data statements */
4029 if (!strcmp(sub->name, "container") ||
4030 !strcmp(sub->name, "leaf-list") ||
4031 !strcmp(sub->name, "leaf") ||
4032 !strcmp(sub->name, "list") ||
4033 !strcmp(sub->name, "choice") ||
4034 !strcmp(sub->name, "uses") ||
4035 !strcmp(sub->name, "grouping") ||
4036 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004037 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004038 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004040 /* array counters */
4041 } else if (!strcmp(sub->name, "typedef")) {
4042 c_tpdf++;
4043 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004044 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 goto error;
4046 }
4047 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004049 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4050 if (c_tpdf) {
4051 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004052 if (!grp->tpdf) {
4053 LOGMEM;
4054 goto error;
4055 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004056 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004057 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004058 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4059 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004060 if (r) {
4061 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004063 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004064
Radek Krejcic071c542016-01-27 14:57:51 +01004065 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004066 goto error;
4067 }
4068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004069 /* last part - process data nodes */
4070 LY_TREE_FOR_SAFE(root.child, next, sub) {
4071 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004072 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004073 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004074 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004075 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004076 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004077 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004078 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004079 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004081 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004083 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004084 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004085 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004086 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004087 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004088 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004089 goto error;
4090 }
Radek Krejci73adb602015-07-02 18:07:40 +02004091
Michal Vasko345da0a2015-12-02 10:35:55 +01004092 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004093 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004095 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004096
4097error:
4098
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004099 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004100 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004101 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004102 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004104 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004105}
4106
Michal Vasko0d343d12015-08-24 14:57:36 +02004107/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004108static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004109read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4110 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004111{
Radek Krejcie0674f82015-06-15 13:58:51 +02004112 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004113 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004114 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004115 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004116 int r;
4117 int c_tpdf = 0;
4118
Radek Krejcie0674f82015-06-15 13:58:51 +02004119 /* init */
4120 memset(&root, 0, sizeof root);
4121
Michal Vasko38d01f72015-06-15 09:41:06 +02004122 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004123 if (!inout) {
4124 LOGMEM;
4125 return NULL;
4126 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004127 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004128
4129 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004130 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004132 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004133 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004134 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004135 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004136 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004137 }
4138
Radek Krejci76512572015-08-04 09:47:08 +02004139 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004140
Radek Krejci6a113852015-07-03 16:04:20 +02004141 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004142 goto error;
4143 }
4144
Radek Krejcia9544502015-08-14 08:24:29 +02004145 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4146
Michal Vasko38d01f72015-06-15 09:41:06 +02004147 /* data statements */
4148 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004149 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4150 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004151 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004152 continue;
4153 }
4154
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004156 !strcmp(sub->name, "leaf-list") ||
4157 !strcmp(sub->name, "leaf") ||
4158 !strcmp(sub->name, "list") ||
4159 !strcmp(sub->name, "choice") ||
4160 !strcmp(sub->name, "uses") ||
4161 !strcmp(sub->name, "grouping") ||
4162 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004163 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004164 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004166 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004167 } else if (!strcmp(sub->name, "typedef")) {
4168 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004169
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004171 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004172 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 }
4174 }
4175
4176 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4177 if (c_tpdf) {
4178 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004179 if (!inout->tpdf) {
4180 LOGMEM;
4181 goto error;
4182 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004183 }
4184
Radek Krejci73adb602015-07-02 18:07:40 +02004185 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004186 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4187 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004188 if (r) {
4189 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004190 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004191 }
4192
Radek Krejcic071c542016-01-27 14:57:51 +01004193 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004194 goto error;
4195 }
4196
Michal Vasko38d01f72015-06-15 09:41:06 +02004197 /* last part - process data nodes */
4198 LY_TREE_FOR_SAFE(root.child, next, sub) {
4199 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004200 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004201 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004202 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004203 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004204 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004205 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004206 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004207 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004208 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004209 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004210 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004211 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004212 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004213 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004215 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004216 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004217 goto error;
4218 }
Radek Krejci73adb602015-07-02 18:07:40 +02004219
Michal Vasko345da0a2015-12-02 10:35:55 +01004220 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004221 }
4222
Michal Vasko38d01f72015-06-15 09:41:06 +02004223 return retval;
4224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004225error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004226
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004227 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004228 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004229 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004230 }
4231
4232 return NULL;
4233}
4234
Michal Vasko0d343d12015-08-24 14:57:36 +02004235/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004236static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004237read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4238 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004239{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004240 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004241 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004242 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004243 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004244 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004245 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004246 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004247
Michal Vaskoc6551b32015-06-16 10:51:43 +02004248 memset(&root, 0, sizeof root);
4249
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004251 if (!notif) {
4252 LOGMEM;
4253 return NULL;
4254 }
Radek Krejci76512572015-08-04 09:47:08 +02004255 notif->nodetype = LYS_NOTIF;
4256 notif->prev = (struct lys_node *)notif;
4257 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004258
Radek Krejci6a113852015-07-03 16:04:20 +02004259 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004260 goto error;
4261 }
4262
Radek Krejcia9544502015-08-14 08:24:29 +02004263 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4264
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 /* process rpc's specific children */
4266 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004267 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4268 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004269 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004270 continue;
4271 }
4272
Michal Vasko0ea41032015-06-16 08:53:55 +02004273 /* data statements */
4274 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004275 !strcmp(sub->name, "leaf-list") ||
4276 !strcmp(sub->name, "leaf") ||
4277 !strcmp(sub->name, "list") ||
4278 !strcmp(sub->name, "choice") ||
4279 !strcmp(sub->name, "uses") ||
4280 !strcmp(sub->name, "grouping") ||
4281 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004282 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004283 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004286 } else if (!strcmp(sub->name, "typedef")) {
4287 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004288 } else if (!strcmp(sub->name, "if-feature")) {
4289 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004290 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004291 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004292 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004293 }
4294 }
4295
4296 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4297 if (c_tpdf) {
4298 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004299 if (!notif->tpdf) {
4300 LOGMEM;
4301 goto error;
4302 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004303 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004304 if (c_ftrs) {
4305 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004306 if (!notif->features) {
4307 LOGMEM;
4308 goto error;
4309 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004310 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004311
Radek Krejci73adb602015-07-02 18:07:40 +02004312 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004313 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004314 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4315 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004316 if (r) {
4317 goto error;
4318 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004319 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004320 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004321 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004322 goto error;
4323 }
Radek Krejcicf509982015-12-15 09:22:44 +01004324 /* hack - store pointer to the parent node for later status check */
4325 notif->features[notif->features_size] = (struct lys_feature *)notif;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004326 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004327 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004328 notif->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004329 lydict_remove(module->ctx, value);
4330 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004331 goto error;
4332 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004333 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004334 }
4335
Radek Krejcic071c542016-01-27 14:57:51 +01004336 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004337 goto error;
4338 }
4339
Michal Vasko0ea41032015-06-16 08:53:55 +02004340 /* last part - process data nodes */
4341 LY_TREE_FOR_SAFE(root.child, next, sub) {
4342 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004343 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004344 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004345 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004346 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004347 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004348 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004349 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004350 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004351 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004352 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004353 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004354 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004355 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004356 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004357 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004358 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004359 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004360 goto error;
4361 }
Radek Krejci73adb602015-07-02 18:07:40 +02004362
Michal Vasko345da0a2015-12-02 10:35:55 +01004363 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004364 }
4365
Michal Vasko0ea41032015-06-16 08:53:55 +02004366 return retval;
4367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004368error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004369
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004370 lys_node_free(retval, NULL);
Michal Vasko0ea41032015-06-16 08:53:55 +02004371 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004372 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004373 }
4374
4375 return NULL;
4376}
4377
Michal Vasko0d343d12015-08-24 14:57:36 +02004378/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004379static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004380read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4381 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004382{
Radek Krejcie0674f82015-06-15 13:58:51 +02004383 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004384 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004385 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004386 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004387 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004388 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004389 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004390
Radek Krejcie0674f82015-06-15 13:58:51 +02004391 /* init */
4392 memset(&root, 0, sizeof root);
4393
Michal Vasko38d01f72015-06-15 09:41:06 +02004394 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004395 if (!rpc) {
4396 LOGMEM;
4397 return NULL;
4398 }
Radek Krejci76512572015-08-04 09:47:08 +02004399 rpc->nodetype = LYS_RPC;
4400 rpc->prev = (struct lys_node *)rpc;
4401 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004402
Radek Krejci6a113852015-07-03 16:04:20 +02004403 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004404 goto error;
4405 }
4406
Radek Krejcia9544502015-08-14 08:24:29 +02004407 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4408
Michal Vasko38d01f72015-06-15 09:41:06 +02004409 /* process rpc's specific children */
4410 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004411 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4412 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004413 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004414 continue;
4415 }
4416
Michal Vasko38d01f72015-06-15 09:41:06 +02004417 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004419 && (rpc->child->nodetype == LYS_INPUT
4420 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004421 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004422 goto error;
4423 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004424 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004425 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004426 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004428 && (rpc->child->nodetype == LYS_INPUT
4429 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004430 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004431 goto error;
4432 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004433 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004434 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004437 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004438 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004439 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004442 } else if (!strcmp(sub->name, "typedef")) {
4443 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004444 } else if (!strcmp(sub->name, "if-feature")) {
4445 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004446 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004447 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004448 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004449 }
4450 }
4451
4452 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4453 if (c_tpdf) {
4454 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004455 if (!rpc->tpdf) {
4456 LOGMEM;
4457 goto error;
4458 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004459 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004460 if (c_ftrs) {
4461 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004462 if (!rpc->features) {
4463 LOGMEM;
4464 goto error;
4465 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004466 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004467
Radek Krejci73adb602015-07-02 18:07:40 +02004468 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004469 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004470 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4471 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004472 if (r) {
4473 goto error;
4474 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004475 } else if (!strcmp(sub->name, "if-feature")) {
4476 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004477 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004478 goto error;
4479 }
Radek Krejcicf509982015-12-15 09:22:44 +01004480 /* hack - store pointer to the parent node for later status check */
4481 rpc->features[rpc->features_size] = (struct lys_feature *)rpc;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004482 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004483 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004484 rpc->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004485 lydict_remove(module->ctx, value);
4486 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004487 goto error;
4488 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004489 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004490 }
4491
Radek Krejcic071c542016-01-27 14:57:51 +01004492 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004493 goto error;
4494 }
4495
Michal Vasko38d01f72015-06-15 09:41:06 +02004496 /* last part - process data nodes */
4497 LY_TREE_FOR_SAFE(root.child, next, sub) {
4498 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004499 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004500 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004501 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004502 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004503 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004504 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004505 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004506 goto error;
4507 }
Radek Krejci73adb602015-07-02 18:07:40 +02004508
Michal Vasko345da0a2015-12-02 10:35:55 +01004509 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004510 }
4511
Michal Vasko38d01f72015-06-15 09:41:06 +02004512 return retval;
4513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004515
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004516 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004517 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004518 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004519 }
4520
4521 return NULL;
4522}
4523
Michal Vasko0d343d12015-08-24 14:57:36 +02004524/* logs directly
4525 *
Radek Krejci74705112015-06-05 10:25:44 +02004526 * resolve - referenced grouping should be bounded to the namespace (resolved)
4527 * only when uses does not appear in grouping. In a case of grouping's uses,
4528 * we just get information but we do not apply augment or refine to it.
4529 */
Radek Krejci76512572015-08-04 09:47:08 +02004530static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004531read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004532 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004533{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004535 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004536 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004538 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004539 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004541 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004542 if (!uses) {
4543 LOGMEM;
4544 return NULL;
4545 }
Radek Krejci76512572015-08-04 09:47:08 +02004546 uses->nodetype = LYS_USES;
4547 uses->prev = (struct lys_node *)uses;
4548 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004549
Radek Krejcia9544502015-08-14 08:24:29 +02004550 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004551 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004552
Michal Vaskoe0c59842015-09-24 13:52:20 +02004553 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4554 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 goto error;
4556 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004557
Radek Krejcia9544502015-08-14 08:24:29 +02004558 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004561 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004562 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4563 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004564 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004565 continue;
4566 }
4567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 if (!strcmp(sub->name, "refine")) {
4569 c_ref++;
4570 } else if (!strcmp(sub->name, "augment")) {
4571 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004572 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004573 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004574 } else if (!strcmp(sub->name, "when")) {
4575 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004576 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004577 goto error;
4578 }
4579
4580 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004581 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004582 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004583 goto error;
4584 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004585 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004586 goto error;
4587 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004588 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004590 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 }
4593 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004595 /* process properties with cardinality 0..n */
4596 if (c_ref) {
4597 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004598 if (!uses->refine) {
4599 LOGMEM;
4600 goto error;
4601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 }
4603 if (c_aug) {
4604 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004605 if (!uses->augment) {
4606 LOGMEM;
4607 goto error;
4608 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004610 if (c_ftrs) {
4611 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004612 if (!uses->features) {
4613 LOGMEM;
4614 goto error;
4615 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004616 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004617
Radek Krejcic071c542016-01-27 14:57:51 +01004618 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004619 goto error;
4620 }
4621
Radek Krejcia9544502015-08-14 08:24:29 +02004622 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004624 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4625 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004626 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004627 goto error;
4628 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004629 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004630 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4631 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004632 if (r) {
4633 goto error;
4634 }
4635 } else if (!strcmp(sub->name, "if-feature")) {
4636 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004637 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004638 goto error;
4639 }
Radek Krejcicf509982015-12-15 09:22:44 +01004640 /* hack - store pointer to the parent node for later status check */
4641 uses->features[uses->features_size] = (struct lys_feature *)uses;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004642 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02004643 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004644 uses->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004645 lydict_remove(module->ctx, value);
4646 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004647 goto error;
4648 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 }
4650 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004651
Michal Vasko0bd29d12015-08-19 11:45:49 +02004652 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004653 goto error;
4654 }
Radek Krejci74705112015-06-05 10:25:44 +02004655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 if (resolve) {
4657 /* inherit config flag */
4658 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004659 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004660 } else {
4661 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004662 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 }
4664 }
Radek Krejcib388c152015-06-04 17:03:03 +02004665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004666 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004667
4668error:
4669
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004670 lys_node_free(retval, NULL);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004673}
4674
Michal Vasko0d343d12015-08-24 14:57:36 +02004675/* logs directly
4676 *
4677 * common code for yin_read_module() and yin_read_submodule()
4678 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679static int
Radek Krejcic071c542016-01-27 14:57:51 +01004680read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4681 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004682{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004684 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004685 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004686 struct lys_module *trg;
4687 struct lys_import *aux_imp;
4688 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004690 int i, j, r;
4691 int inc_size_aux = 0;
4692 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004693 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004694 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 +02004695
Radek Krejcic071c542016-01-27 14:57:51 +01004696 /* to simplify code, store the module/submodule being processed as trg */
4697 trg = submodule ? (struct lys_module*)submodule : module;
4698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 /* init */
4700 memset(&root, 0, sizeof root);
4701 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004702 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 /*
4705 * in the first run, we process elements with cardinality of 1 or 0..1 and
4706 * count elements with cardinality 0..n. Data elements (choices, containers,
4707 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4708 * need have all top-level and groupings already prepared at that time. In
4709 * the middle loop, we process other elements with carinality of 0..n since
4710 * we need to allocate arrays to store them.
4711 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 LY_TREE_FOR_SAFE(yin->child, next, child) {
4713 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004714 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004715 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 continue;
4717 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004718
Radek Krejcic071c542016-01-27 14:57:51 +01004719 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004720 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004721 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 goto error;
4723 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004724 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004725 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004726 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004727 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004729 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 goto error;
4731 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004732 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004733 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 goto error;
4735 }
4736 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004737 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004738 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4739 if (submodule->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004740 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 goto error;
4742 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004743 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004745 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 goto error;
4747 }
Radek Krejcif3886932015-06-04 17:36:06 +02004748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004750 if (!child->child) {
4751 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004753 } else if (strcmp(child->child->name, "prefix")) {
4754 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004755 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004756 } else if (child->child->next) {
4757 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 goto error;
4759 }
4760 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004761 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004762 /* check here differs from a generic prefix check, since this prefix
4763 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004764 */
Radek Krejcic6556022016-01-27 15:16:45 +01004765 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 goto error;
4767 }
Radek Krejcic071c542016-01-27 14:57:51 +01004768 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004771 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004772
4773 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004776 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004778 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004779 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004780 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004781 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004782 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004783 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004784 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004785 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004786 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004787 lyxml_unlink_elem(ctx, child, 2);
4788 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004789
Radek Krejci1d82ef62015-08-07 14:44:40 +02004790 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004791 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004792 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004793 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004795 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004796 } else if (!strcmp(child->name, "container") ||
4797 !strcmp(child->name, "leaf-list") ||
4798 !strcmp(child->name, "leaf") ||
4799 !strcmp(child->name, "list") ||
4800 !strcmp(child->name, "choice") ||
4801 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004802 !strcmp(child->name, "anyxml") ||
4803 !strcmp(child->name, "rpc") ||
4804 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004805 lyxml_unlink_elem(ctx, child, 2);
4806 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004807
Radek Krejci1d82ef62015-08-07 14:44:40 +02004808 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004810 lyxml_unlink_elem(ctx, child, 2);
4811 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004814 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004815 if (trg->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004816 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 goto error;
4818 }
Radek Krejcic071c542016-01-27 14:57:51 +01004819 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004820 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004821 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 goto error;
4823 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004824 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004825 if (trg->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004826 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004827 goto error;
4828 }
Radek Krejcic071c542016-01-27 14:57:51 +01004829 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004830 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004831 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004832 goto error;
4833 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004834 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004835 if (trg->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004836 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837 goto error;
4838 }
Radek Krejcic071c542016-01-27 14:57:51 +01004839 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004840 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004841 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 goto error;
4843 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004844 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004845 if (trg->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004846 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847 goto error;
4848 }
Radek Krejcic071c542016-01-27 14:57:51 +01004849 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004850 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004851 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 goto error;
4853 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004854 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004855 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004856 if (version_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004857 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004858 goto error;
4859 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004860 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004862 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 goto error;
4864 }
Radek Krejcic071c542016-01-27 14:57:51 +01004865 version_flag = 1;
4866 if (!submodule) {
4867 module->version = 1;
4868 } /* 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 +01004869 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004870
Radek Krejci1d82ef62015-08-07 14:44:40 +02004871 } else if (!strcmp(child->name, "extension")) {
4872 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004873
Radek Krejci3d468122015-10-02 13:36:12 +02004874 /* we have the following supported (hardcoded) extensions: */
4875 /* ietf-netconf's get-filter-element-attributes */
4876 if (!strcmp(module->ns, LY_NSNC) &&
4877 !strcmp(value, "get-filter-element-attributes")) {
4878 LOGDBG("NETCONF filter extension found");
4879 /* NACM's default-deny-write and default-deny-all */
4880 } else if (!strcmp(module->ns, LY_NSNACM) &&
4881 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4882 LOGDBG("NACM extension found");
4883 /* other extensions are not supported, so inform about such an extension */
4884 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004885 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004886 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004887 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004889 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 }
4892 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004893
Radek Krejcic071c542016-01-27 14:57:51 +01004894 /* check for mandatory statements */
4895 if (submodule && !submodule->prefix) {
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004896 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "belongs-to", "submodule");
4897 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004898 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004899 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004900 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 goto error;
4902 }
4903 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004904 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 goto error;
4906 }
4907 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 /* allocate arrays for elements with cardinality of 0..n */
4910 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004911 trg->imp = calloc(c_imp, sizeof *trg->imp);
4912 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004913 LOGMEM;
4914 goto error;
4915 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 }
4917 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004918 trg->rev = calloc(c_rev, sizeof *trg->rev);
4919 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004920 LOGMEM;
4921 goto error;
4922 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004923 }
4924 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004925 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4926 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004927 LOGMEM;
4928 goto error;
4929 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004930 }
4931 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004932 trg->ident = calloc(c_ident, sizeof *trg->ident);
4933 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004934 LOGMEM;
4935 goto error;
4936 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 }
4938 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004939 trg->inc = calloc(c_inc, sizeof *trg->inc);
4940 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004941 LOGMEM;
4942 goto error;
4943 }
Radek Krejcic071c542016-01-27 14:57:51 +01004944 trg->inc_size = c_inc;
4945 /* trg->inc_size can be updated by the included submodules,
4946 * so we will use inc_size_aux here, trg->inc_size stores the
4947 * target size of the array
4948 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004949 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004950 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004951 trg->augment = calloc(c_aug, sizeof *trg->augment);
4952 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004953 LOGMEM;
4954 goto error;
4955 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004956 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004957 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004958 trg->features = calloc(c_ftrs, sizeof *trg->features);
4959 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004960 LOGMEM;
4961 goto error;
4962 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004963 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004964 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004965 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4966 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004967 LOGMEM;
4968 goto error;
4969 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004970 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004971
Michal Vasko2f7925f2015-10-21 15:06:56 +02004972 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4973 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004974 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004975 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4976 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004977 if (r) {
4978 goto error;
4979 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004980
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004981 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004982 for (i = 0; i < trg->imp_size - 1; i++) {
4983 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
4984 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 goto error;
4986 }
4987 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004988
Radek Krejci1d82ef62015-08-07 14:44:40 +02004989 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004990 memset(&inc, 0, sizeof inc);
4991 /* 1) pass module, not trg, since we want to pass the main module
4992 * 2) we cannot pass directly the structure in the array since
4993 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004994 r = fill_yin_include(module, submodule, child, &inc, unres);
Michal Vasko9c4c99d2016-02-11 15:47:08 +01004995 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4996 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 if (r) {
4998 goto error;
4999 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01005002 for (i = 0; i < inc_size_aux - 1; i++) {
Michal Vasko27ab8222016-02-12 09:33:52 +01005003 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005004 LOGVAL(LYE_SPEC, LOGLINE(child), "Including submodule \"%s\" repeatedly.",
Michal Vasko27ab8222016-02-12 09:33:52 +01005005 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 goto error;
5007 }
5008 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005009
Radek Krejci1d82ef62015-08-07 14:44:40 +02005010 } else if (!strcmp(child->name, "revision")) {
5011 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01005012 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 goto error;
5014 }
Radek Krejcic071c542016-01-27 14:57:51 +01005015 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005017 for (i = 0; i < trg->rev_size; i++) {
5018 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005019 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005020 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 }
5022 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005023
Radek Krejci1d82ef62015-08-07 14:44:40 +02005024 LY_TREE_FOR(child->child, child2) {
5025 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005026 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005027 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 goto error;
5029 }
Radek Krejcic071c542016-01-27 14:57:51 +01005030 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5031 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 goto error;
5033 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005034 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005035 if (trg->rev[trg->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005036 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 goto error;
5038 }
Radek Krejcic071c542016-01-27 14:57:51 +01005039 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5040 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005041 goto error;
5042 }
5043 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005044 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005045 goto error;
5046 }
5047 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005050 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005051 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005052 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005053 if (!value) {
5054 LOGMEM;
5055 goto error;
5056 }
Radek Krejcic071c542016-01-27 14:57:51 +01005057 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5058 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005059 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005060
Radek Krejcic071c542016-01-27 14:57:51 +01005061 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
5062 value = trg->rev[0].dsc;
5063 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5064 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005066
Radek Krejcic071c542016-01-27 14:57:51 +01005067 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
5068 value = trg->rev[0].ref;
5069 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5070 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005071 }
5072 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005073
Radek Krejcic071c542016-01-27 14:57:51 +01005074 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005075
Radek Krejci1d82ef62015-08-07 14:44:40 +02005076 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005077 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5078 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005079 if (r) {
5080 goto error;
5081 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005082
Radek Krejci1d82ef62015-08-07 14:44:40 +02005083 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005084 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5085 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005086 if (r) {
5087 goto error;
5088 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005089
Radek Krejci1d82ef62015-08-07 14:44:40 +02005090 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005091 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5092 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005093 if (r) {
5094 goto error;
5095 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005096
Radek Krejci1d82ef62015-08-07 14:44:40 +02005097 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005098 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5099 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005100 if (r) {
5101 goto error;
5102 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005103 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5104 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005107 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005108
Radek Krejcic071c542016-01-27 14:57:51 +01005109 if (submodule) {
5110 /* propagate imports into the main module */
5111 for (i = r = 0; i < submodule->imp_size; i++) {
5112 for (j = 0; j < module->imp_size; j++) {
5113 if (submodule->imp[i].module == module->imp[j].module &&
5114 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5115 /* check prefix match */
5116 if (submodule->imp[i].prefix != module->imp[j].prefix) {
5117 LOGVAL(LYE_INID, LOGLINE(yin), submodule->imp[i].prefix,
5118 "non-matching prefixes of imported module in main module and submodule");
5119 goto error;
5120 }
5121 break;
5122 }
5123 }
5124 if (j == module->imp_size) {
5125 /* new import */
5126 r++;
5127 }
5128 }
5129 if (r) {
5130 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5131 if (!aux_imp) {
5132 LOGMEM;
5133 goto error;
5134 }
5135 module->imp = aux_imp;
5136 for (i = r = 0; i < submodule->imp_size; i++) {
5137 for (j = 0; j < module->imp_size; j++) {
5138 if (submodule->imp[i].module == module->imp[j].module) {
5139 break;
5140 }
5141 }
5142 if (j == module->imp_size) {
5143 /* new import */
5144 /* check prefix uniqueness */
5145 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
5146 LOGVAL(LYE_DUPID, LOGLINE(yin), "prefix", submodule->imp[i].prefix);
5147 goto error;
5148 }
5149 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5150 module->imp[module->imp_size + r].external = 1;
5151 r++;
5152 }
5153 }
5154 module->imp_size += r;
5155 }
5156
Michal Vaskoe2905632016-02-11 15:42:24 +01005157 /* propagate includes into the main module */
Radek Krejcic071c542016-01-27 14:57:51 +01005158 for (i = r = 0; i < submodule->inc_size; i++) {
5159 for (j = 0; j < module->inc_size; j++) {
5160 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5161 break;
5162 }
5163 }
5164 if (j == module->inc_size) {
5165 /* new include */
5166 r++;
5167 }
5168 }
5169
5170 if (r) {
5171 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5172 if (!aux_inc) {
5173 LOGMEM;
5174 goto error;
5175 }
5176 module->inc = aux_inc;
5177 for (i = r = 0; i < submodule->inc_size; i++) {
5178 for (j = 0; j < module->inc_size; j++) {
5179 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5180 break;
5181 }
5182 }
5183 if (j == module->inc_size) {
5184 /* new include */
5185 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5186 module->inc[module->inc_size + r].external = 1;
5187 r++;
5188 }
5189 }
5190 module->inc_size += r;
5191 }
5192 }
5193
Radek Krejcif5be10f2015-06-16 13:29:36 +02005194 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005195 * refer to them. Submodule's data nodes are stored in the
5196 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005198 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005199 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005200 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005201 goto error;
5202 }
Radek Krejci74705112015-06-05 10:25:44 +02005203
Michal Vasko345da0a2015-12-02 10:35:55 +01005204 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 }
Radek Krejci74705112015-06-05 10:25:44 +02005206
Radek Krejcif5be10f2015-06-16 13:29:36 +02005207 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005208 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005209
Radek Krejci1d82ef62015-08-07 14:44:40 +02005210 if (!strcmp(child->name, "container")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005211 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005212 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005213 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005214 } else if (!strcmp(child->name, "leaf")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005215 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005216 } else if (!strcmp(child->name, "list")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005217 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005218 } else if (!strcmp(child->name, "choice")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005219 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005220 } else if (!strcmp(child->name, "uses")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005221 node = read_yin_uses(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005222 } else if (!strcmp(child->name, "anyxml")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005223 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005224 } else if (!strcmp(child->name, "rpc")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005225 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005226 } else if (!strcmp(child->name, "notification")) {
Michal Vasko43b9d952016-02-15 11:07:03 +01005227 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005228 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005229 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 goto error;
5231 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005232
Michal Vasko345da0a2015-12-02 10:35:55 +01005233 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005234 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005235
Michal Vasko2f7925f2015-10-21 15:06:56 +02005236 /* ... and finally augments (last, so we can augment our data, for instance) */
5237 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005238 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5239 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005240
Michal Vasko2f7925f2015-10-21 15:06:56 +02005241 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005242 goto error;
5243 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005244 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005245 }
5246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005248
5249error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005250 /* cleanup */
5251 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005252 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 }
5254 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005255 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005256 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005257 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005258 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005259 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005262}
5263
Michal Vasko0d343d12015-08-24 14:57:36 +02005264/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005265struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01005266yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005267{
Michal Vasko9f258e42016-02-11 11:36:27 +01005268 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005270 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 const char *value;
Michal Vasko9f258e42016-02-11 11:36:27 +01005272 uint8_t i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005275
Radek Krejci722b0072016-02-01 17:09:45 +01005276 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 if (!yin) {
5278 return NULL;
5279 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 /* check root element */
5282 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005283 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005284 goto error;
5285 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005287 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005288 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 goto error;
5290 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 submodule = calloc(1, sizeof *submodule);
5293 if (!submodule) {
5294 LOGMEM;
5295 goto error;
5296 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 submodule->ctx = module->ctx;
5299 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5300 submodule->type = 1;
5301 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005302
Michal Vasko9f258e42016-02-11 11:36:27 +01005303 LOGVRB("Reading submodule \"%s\".", submodule->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005304 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005305 goto error;
5306 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005309 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005310
Michal Vasko9f258e42016-02-11 11:36:27 +01005311 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005314
5315error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005317 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005318 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005319
Radek Krejcidaea8212016-02-15 08:28:20 +01005320 if (!submodule) {
5321 LOGERR(ly_errno, "Submodule parsing failed.");
5322 return NULL;
5323 }
5324
5325 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
5326
Michal Vasko9f258e42016-02-11 11:36:27 +01005327 /* warn about applied deviations */
5328 for (i = 0; i < submodule->deviation_size; ++i) {
Michal Vasko60f4b452016-02-12 11:02:55 +01005329 if (submodule->deviation[i].target_module) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005330 LOGERR(ly_errno, "Submodule parsing failed, but successfully deviated %smodule \"%s\".",
Michal Vasko60f4b452016-02-12 11:02:55 +01005331 (submodule->deviation[i].target_module->type ? "sub" : ""),
5332 submodule->deviation[i].target_module->name);
Michal Vasko9f258e42016-02-11 11:36:27 +01005333 }
5334 }
5335
5336 /* remove applied augments */
5337 for (i = 0; i < submodule->augment_size; ++i) {
5338 if (submodule->augment[i].target) {
5339 LY_TREE_FOR_SAFE(submodule->augment[i].target->child, next, elem) {
5340 if (elem->parent == (struct lys_node *)&submodule->augment[i]) {
5341 lys_node_free(elem, NULL);
5342 }
5343 }
5344 }
5345 }
5346
5347 lys_submodule_free(submodule, NULL);
Radek Krejciefaeba32015-05-27 14:30:57 +02005348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005349 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005350}
5351
Michal Vasko0d343d12015-08-24 14:57:36 +02005352/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005353struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005354yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005355{
Michal Vasko9f258e42016-02-11 11:36:27 +01005356 struct lys_node *next, *elem;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005358 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005359 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 const char *value;
5361 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005362
Radek Krejcic071c542016-01-27 14:57:51 +01005363 unres = calloc(1, sizeof *unres);
5364 if (!unres) {
5365 LOGMEM;
5366 return NULL;
5367 }
5368
Radek Krejci722b0072016-02-01 17:09:45 +01005369 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005370 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005371 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005372 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005374 /* check root element */
5375 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005376 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005377 goto error;
5378 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005380 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005381 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005382 goto error;
5383 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005385 module = calloc(1, sizeof *module);
5386 if (!module) {
5387 LOGMEM;
5388 goto error;
5389 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005391 module->ctx = ctx;
5392 module->name = lydict_insert(ctx, value, strlen(value));
5393 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005394 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005395
Michal Vasko9f258e42016-02-11 11:36:27 +01005396 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005397 if (read_sub_module(module, NULL, yin, unres)) {
5398 goto error;
5399 }
5400
5401 /* resolve rest of unres items */
5402 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005403 goto error;
5404 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005406 /* add to the context's list of modules */
5407 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005408 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005409 if (!newlist) {
5410 LOGMEM;
5411 goto error;
5412 }
5413 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5414 newlist[i] = NULL;
5415 }
5416 ctx->models.size *= 2;
5417 ctx->models.list = newlist;
5418 }
5419 for (i = 0; ctx->models.list[i]; i++) {
5420 /* check name (name/revision) and namespace uniqueness */
5421 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005422 if (ctx->models.list[i]->rev_size == module->rev_size) {
5423 /* both have the same number of revisions */
5424 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5425 /* both have the same revision -> we already have the same module */
5426 /* so free the new one and update the old one's implement flag if needed */
Michal Vasko9f258e42016-02-11 11:36:27 +01005427 LOGVRB("Module \"%s\" already in context.", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005428
Michal Vasko9f258e42016-02-11 11:36:27 +01005429 lys_free(module, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01005430 module = ctx->models.list[i];
5431 if (implement && !module->implemented) {
5432 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005433 }
Radek Krejcic071c542016-01-27 14:57:51 +01005434
5435 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 }
5437 }
Radek Krejcif647e612015-07-30 11:36:07 +02005438 /* else (both elses) keep searching, for now the caller is just adding
5439 * another revision of an already present schema
5440 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005441 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005442 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 ctx->models.list[i]->name, module->name, module->ns);
5444 goto error;
5445 }
5446 }
5447 ctx->models.list[i] = module;
5448 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005449 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005450
Radek Krejcic071c542016-01-27 14:57:51 +01005451success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005452 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005453 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005454 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005455
Michal Vasko9f258e42016-02-11 11:36:27 +01005456 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005458 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005459
5460error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005461 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005462 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005463 unres_schema_free(module, &unres);
5464
5465 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005466 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005467 return NULL;
5468 }
5469
5470 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005471
Michal Vasko9f258e42016-02-11 11:36:27 +01005472 /* warn about applied deviations */
5473 for (i = 0; i < module->deviation_size; ++i) {
Michal Vasko60f4b452016-02-12 11:02:55 +01005474 if (module->deviation[i].target_module) {
Michal Vasko9f258e42016-02-11 11:36:27 +01005475 LOGERR(ly_errno, "Module parsing failed, but successfully deviated %smodule \"%s\".",
Michal Vasko60f4b452016-02-12 11:02:55 +01005476 (module->deviation[i].target_module->type ? "sub" : ""),
5477 module->deviation[i].target_module->name);
Michal Vasko9f258e42016-02-11 11:36:27 +01005478 }
5479 }
5480
5481 /* remove applied augments */
5482 for (i = 0; i < module->augment_size; ++i) {
5483 if (module->augment[i].target) {
5484 LY_TREE_FOR_SAFE(module->augment[i].target->child, next, elem) {
5485 if (elem->parent == (struct lys_node *)&module->augment[i]) {
5486 lys_node_free(elem, NULL);
5487 }
5488 }
5489 }
5490 }
5491
5492 lys_free(module, NULL, 1);
5493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005494 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005495}