blob: 89a45a7b6fa889e00f4052d3a449ad9597669473 [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)) {
88 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
89 } else if (node->child->content) {
90 len = strlen(node->child->content);
91 return lydict_insert(ctx, node->child->content, len);
92 }
Radek Krejcice7fb782015-05-29 16:52:34 +020093
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020094 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020095 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +020096}
97
Michal Vasko0d343d12015-08-24 14:57:36 +020098/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020099static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200100fill_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 +0200101{
Radek Krejci73adb602015-07-02 18:07:40 +0200102 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200103 const char *value;
Radek Krejci04581c62015-05-22 21:24:00 +0200104
Michal Vasko4cfcd252015-08-03 14:31:10 +0200105 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100106 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200107
Radek Krejci76512572015-08-04 09:47:08 +0200108 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200109 return EXIT_FAILURE;
110 }
Radek Krejci04581c62015-05-22 21:24:00 +0200111
Radek Krejci73adb602015-07-02 18:07:40 +0200112 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200113 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
114 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200115 continue;
116 }
117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200118 if (!strcmp(node->name, "base")) {
119 if (ident->base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200120 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200121 return EXIT_FAILURE;
122 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200123 GETVAL(value, node, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100124 value = transform_schema2json(module, value, LOGLINE(node));
125 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200126 return EXIT_FAILURE;
127 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100128
129 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
130 lydict_remove(module->ctx, value);
131 return EXIT_FAILURE;
132 }
133 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200134 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200135 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200136 return EXIT_FAILURE;
137 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200138 }
Radek Krejci04581c62015-05-22 21:24:00 +0200139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200140 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200141
142error:
143 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200144}
145
Michal Vasko0d343d12015-08-24 14:57:36 +0200146/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200147static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200148read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200149{
Radek Krejci73adb602015-07-02 18:07:40 +0200150 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200151 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200152
Radek Krejci73adb602015-07-02 18:07:40 +0200153 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200154 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
155 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200156 continue;
157 }
158
Radek Krejci41726f92015-06-19 13:11:05 +0200159 if (!strcmp(child->name, "description")) {
160 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200161 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200162 return EXIT_FAILURE;
163 }
164 restr->dsc = read_yin_subnode(ctx, child, "text");
165 if (!restr->dsc) {
166 return EXIT_FAILURE;
167 }
168 } else if (!strcmp(child->name, "reference")) {
169 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200170 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200171 return EXIT_FAILURE;
172 }
173 restr->ref = read_yin_subnode(ctx, child, "text");
174 if (!restr->ref) {
175 return EXIT_FAILURE;
176 }
177 } else if (!strcmp(child->name, "error-app-tag")) {
178 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200179 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200180 return EXIT_FAILURE;
181 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200182 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200183 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200184 } else if (!strcmp(child->name, "error-message")) {
185 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200186 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200187 return EXIT_FAILURE;
188 }
189 restr->emsg = read_yin_subnode(ctx, child, "value");
190 if (!restr->emsg) {
191 return EXIT_FAILURE;
192 }
193 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200194 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200195 return EXIT_FAILURE;
196 }
Radek Krejci41726f92015-06-19 13:11:05 +0200197 }
198
199 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200200
201error:
202 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200203}
204
Michal Vasko88c29542015-11-27 14:57:53 +0100205/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
206int
Radek Krejcib8048692015-08-05 13:36:34 +0200207fill_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 +0200208 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200209{
Michal Vasko1dca6882015-10-22 14:29:42 +0200210 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200211 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200212 struct lys_restr **restr;
213 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200214 pcre *precomp;
215 int i, j, rc, err_offset;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200216 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200217 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200218
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200219 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200220 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200221 if (!value) {
222 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200223 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200224
225 i = parse_identifier(value);
226 if (i < 1) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200227 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100228 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200229 goto error;
230 }
231 /* module name */
232 if (value[i]) {
233 type->module_name = lydict_insert(module->ctx, value, i);
234 value += i;
Michal Vasko534f8442015-10-21 13:25:49 +0200235 if ((value[0] != ':') || (parse_identifier(value + 1) < 1)) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200236 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[0], value);
Michal Vasko88c29542015-11-27 14:57:53 +0100237 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200238 goto error;
239 }
Michal Vasko534f8442015-10-21 13:25:49 +0200240 ++value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200241 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200242
Michal Vasko1dca6882015-10-22 14:29:42 +0200243 rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100244 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200245 if (rc == -1) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200246 LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200247 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100248
249 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200250 } else if (rc == EXIT_FAILURE) {
Michal Vasko88c29542015-11-27 14:57:53 +0100251 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200252 }
253 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200254
Radek Krejcicf509982015-12-15 09:22:44 +0100255 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100256 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejcicf509982015-12-15 09:22:44 +0100257 type->der->flags, type->der->module, type->der->name, LOGLINE(yin))) {
258 return -1;
259 }
260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200261 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200262 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200263 /* RFC 6020 9.7.4 - bit */
264
265 /* get bit specifications, at least one must be present */
266 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200267 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
268 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100269 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200270 continue;
271 }
272
Radek Krejci994b6f62015-06-18 16:47:27 +0200273 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200274 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200275 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100276 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200277 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200278 }
279 }
Radek Krejciac781922015-07-09 15:35:14 +0200280 if (!type->der->type.der && !type->info.bits.count) {
281 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200282 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200283 goto error;
284 }
Radek Krejciac781922015-07-09 15:35:14 +0200285 if (type->der->type.der && type->info.bits.count) {
286 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200287 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200288 goto error;
289 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200290
291 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100292 if (!type->info.bits.bit) {
293 LOGMEM;
294 goto error;
295 }
Radek Krejci73adb602015-07-02 18:07:40 +0200296 p = 0;
297 i = -1;
298 LY_TREE_FOR(yin->child, next) {
299 i++;
300
301 GETVAL(value, next, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100302 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100303 goto error;
304 }
305
Radek Krejci994b6f62015-06-18 16:47:27 +0200306 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200307 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200308 type->info.bits.count = i + 1;
309 goto error;
310 }
311
312 /* check the name uniqueness */
313 for (j = 0; j < i; j++) {
314 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200315 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200316 type->info.bits.count = i + 1;
317 goto error;
318 }
319 }
320
Radek Krejci0d70c372015-07-02 16:23:10 +0200321 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200322 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200323 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
324 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200325 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200326 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200327
Radek Krejci0d70c372015-07-02 16:23:10 +0200328 if (!strcmp(node->name, "position")) {
329 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200330 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200331
332 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200333 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200334 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200335 type->info.bits.count = i + 1;
336 goto error;
337 }
338 type->info.bits.bit[i].pos = (uint32_t)p_;
339
340 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200341 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200342 p = type->info.bits.bit[i].pos;
343 p++;
344 } else {
345 /* check that the value is unique */
346 for (j = 0; j < i; j++) {
347 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200348 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 +0200349 type->info.bits.count = i + 1;
350 goto error;
351 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200352 }
353 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200354 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100355 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200356 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200357 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200358 }
359 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200360 /* assign value automatically */
361 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200362 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200363 type->info.bits.count = i + 1;
364 goto error;
365 }
366 type->info.bits.bit[i].pos = (uint32_t)p;
367 p++;
368 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200369
370 /* keep them ordered by position */
371 j = i;
372 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
373 /* switch them */
374 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
375 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
376 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
377 j--;
378 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200379 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200380 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200382 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200383 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200384 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200385 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
386 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200387 continue;
388 }
389
Radek Krejcif9401c32015-06-26 16:47:36 +0200390 if (!strcmp(node->name, "range")) {
391 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200392 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200393 goto error;
394 }
395
396 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200397 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200398 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200399 goto error;
400 }
401 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100402 if (!type->info.dec64.range) {
403 LOGMEM;
404 goto error;
405 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200406 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
407
408 /* get possible substatements */
409 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
410 goto error;
411 }
412 } else if (!strcmp(node->name, "fraction-digits")) {
413 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200414 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200415 goto error;
416 }
417 GETVAL(value, node, "value");
418 v = strtol(value, NULL, 10);
419
420 /* range check */
421 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200422 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200423 goto error;
424 }
425 type->info.dec64.dig = (uint8_t)v;
426 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200427 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200428 goto error;
429 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200430 }
431
432 /* mandatory sub-statement(s) check */
433 if (!type->info.dec64.dig && !type->der->type.der) {
434 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200435 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200436 goto error;
437 }
Radek Krejci7511f402015-07-10 09:56:30 +0200438 if (type->info.dec64.dig && type->der->type.der) {
439 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200440 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200441 goto error;
442 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200443 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200445 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200446 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200447
Radek Krejci994b6f62015-06-18 16:47:27 +0200448 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200449 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200450 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
451 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100452 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200453 continue;
454 }
455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200456 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200457 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200458 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100459 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200460 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200461 }
462 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200463 if (!type->der->type.der && !type->info.enums.count) {
464 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200465 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200466 goto error;
467 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200468 if (type->der->type.der && type->info.enums.count) {
469 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200470 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200471 goto error;
472 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200473
Radek Krejci1574a8d2015-08-03 14:16:52 +0200474 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100475 if (!type->info.enums.enm) {
476 LOGMEM;
477 goto error;
478 }
Radek Krejci73adb602015-07-02 18:07:40 +0200479 v = 0;
480 i = -1;
481 LY_TREE_FOR(yin->child, next) {
482 i++;
483
484 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100485 if (!value[0]) {
486 LOGVAL(LYE_SPEC, LOGLINE(next), "Enum name must not be empty.");
487 goto error;
488 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200489 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200490 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200491 type->info.enums.count = i + 1;
492 goto error;
493 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200495 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200496 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200497 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200498 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 type->info.enums.count = i + 1;
500 goto error;
501 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200503 /* check the name uniqueness */
504 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200505 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200506 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200507 type->info.enums.count = i + 1;
508 goto error;
509 }
510 }
Radek Krejci04581c62015-05-22 21:24:00 +0200511
Radek Krejci0d70c372015-07-02 16:23:10 +0200512 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200513 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200514 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
515 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200516 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200517 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200518
Radek Krejci0d70c372015-07-02 16:23:10 +0200519 if (!strcmp(node->name, "value")) {
520 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200521 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200522
523 /* range check */
524 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200525 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200526 type->info.enums.count = i + 1;
527 goto error;
528 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200529 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200530
531 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200532 if (type->info.enums.enm[i].value > v) {
533 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200534 v++;
535 } else {
536 /* check that the value is unique */
537 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200538 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200539 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200540 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200541 type->info.enums.count = i + 1;
542 goto error;
543 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200544 }
545 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200546 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100547 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200548 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200549 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200550 }
551 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200552 /* assign value automatically */
553 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200554 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200555 type->info.enums.count = i + 1;
556 goto error;
557 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200558 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200559 v++;
560 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200561 }
562 break;
563
564 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200565 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200566
567 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200568 LY_TREE_FOR_SAFE(yin->child, next, node) {
569 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
570 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100571 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200572 continue;
573 }
574
Michal Vaskoe29c6622015-11-27 15:02:31 +0100575 if (strcmp(node->name, "base")) {
576 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200577 goto error;
578 }
579 }
580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200582 if (type->der->type.der) {
583 /* this is just a derived type with no base specified/required */
584 break;
585 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200586 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 goto error;
588 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200590 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 goto error;
592 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200593 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100594 /* store in the JSON format */
595 value = transform_schema2json(module, value, LOGLINE(yin->child));
596 if (!value) {
597 goto error;
598 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200599 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200600 goto error;
601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602 break;
603
604 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200605 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200606 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200607 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
608 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200609 continue;
610 }
611
Radek Krejciaf351422015-06-19 14:49:38 +0200612 if (!strcmp(node->name, "require-instance")) {
613 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200614 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200615 goto error;
616 }
617 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200618 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200619 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200620 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200621 type->info.inst.req = -1;
622 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200623 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200624 goto error;
625 }
626 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200627 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200628 goto error;
629 }
Radek Krejciaf351422015-06-19 14:49:38 +0200630 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632 break;
633
Radek Krejcif2860132015-06-20 12:37:20 +0200634 case LY_TYPE_BINARY:
635 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 case LY_TYPE_INT8:
637 case LY_TYPE_INT16:
638 case LY_TYPE_INT32:
639 case LY_TYPE_INT64:
640 case LY_TYPE_UINT8:
641 case LY_TYPE_UINT16:
642 case LY_TYPE_UINT32:
643 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200644 /* RFC 6020 9.2.4 - range */
645
646 /* length and range are actually the same restriction, so process
647 * them by this common code, we just need to differ the name and
648 * structure where the information will be stored
649 */
650 if (type->base == LY_TYPE_BINARY) {
651 restr = &type->info.binary.length;
652 name = "length";
653 } else {
654 restr = &type->info.num.range;
655 name = "range";
656 }
657
Radek Krejci73adb602015-07-02 18:07:40 +0200658 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200659 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
660 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200661 continue;
662 }
663
Radek Krejcif2860132015-06-20 12:37:20 +0200664 if (!strcmp(node->name, name)) {
665 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200666 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200667 goto error;
668 }
669
670 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200671 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200672 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200673 goto error;
674 }
675 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100676 if (!(*restr)) {
677 LOGMEM;
678 goto error;
679 }
Radek Krejcif2860132015-06-20 12:37:20 +0200680 (*restr)->expr = lydict_insert(module->ctx, value, 0);
681
682 /* get possible substatements */
683 if (read_restr_substmt(module->ctx, *restr, node)) {
684 goto error;
685 }
686 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200687 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200688 goto error;
689 }
Radek Krejcif2860132015-06-20 12:37:20 +0200690 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 break;
692
693 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200694 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200695 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200696 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
697 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200698 continue;
699 }
700
Michal Vasko88c29542015-11-27 14:57:53 +0100701 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200702 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200703 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200704 goto error;
705 }
706
707 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200708 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200709 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200710 if (!type->info.lref.path) {
711 goto error;
712 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200713 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200714 goto error;
715 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200716
Radek Krejcidc4c1412015-06-19 15:39:54 +0200717 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200718 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200719 goto error;
720 }
Radek Krejci73adb602015-07-02 18:07:40 +0200721 }
722
Michal Vasko88c29542015-11-27 14:57:53 +0100723 if (!type->info.lref.path && !type->der->type.der) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200724 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200725 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200726 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 break;
728
729 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200730 /* RFC 6020 9.4.4 - length */
731 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200732 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200733 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200734 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
735 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100736 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200737 continue;
738 }
739
Radek Krejci3733a802015-06-19 13:43:21 +0200740 if (!strcmp(node->name, "length")) {
741 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200742 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200743 goto error;
744 }
745
746 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200747 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200748 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200749 goto error;
750 }
751 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100752 if (!type->info.str.length) {
753 LOGMEM;
754 goto error;
755 }
Radek Krejci3733a802015-06-19 13:43:21 +0200756 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
757
Radek Krejci5fbc9162015-06-19 14:11:11 +0200758 /* get possible sub-statements */
759 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200760 goto error;
761 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100762 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200763 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200764 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200765 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200766 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200767 goto error;
768 }
769 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200770 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200771 if (i) {
772 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100773 if (!type->info.str.patterns) {
774 LOGMEM;
775 goto error;
776 }
Radek Krejci73adb602015-07-02 18:07:40 +0200777 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100778 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200779
780 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200781 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
782 if (!precomp) {
783 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200784 free(type->info.str.patterns);
785 goto error;
786 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200787 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200788
Radek Krejci73adb602015-07-02 18:07:40 +0200789 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200790
791 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100792 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200793 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200794 goto error;
795 }
Radek Krejci73adb602015-07-02 18:07:40 +0200796 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200797 }
798 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200799 break;
800
801 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200802 /* RFC 6020 7.4 - type */
803 /* count number of types in union */
804 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200805 LY_TREE_FOR_SAFE(yin->child, next, node) {
806 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
807 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100808 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200809 continue;
810 }
811
Radek Krejcie4c366b2015-07-02 10:11:31 +0200812 if (!strcmp(node->name, "type")) {
813 i++;
814 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200815 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200816 goto error;
817 }
818 }
819
820 if (!i) {
821 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100822 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200823 break;
824 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200825 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200826 goto error;
827 }
828
829 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200830 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100831 if (!type->info.uni.types) {
832 LOGMEM;
833 goto error;
834 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200835 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200836 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100837 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100838 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
839 if (!rc) {
840 type->info.uni.count++;
841
842 /* union's type cannot be empty or leafref */
843 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
844 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
845 rc = -1;
846 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
847 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
848 rc = -1;
849 }
850 }
851 if (rc) {
852 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
853 for (i = 0; i < type->info.uni.count; ++i) {
854 lys_type_free(module->ctx, &type->info.uni.types[i]);
855 }
856 free(type->info.uni.types);
857 type->info.uni.types = NULL;
858 type->info.uni.count = 0;
859
860 if (rc == EXIT_FAILURE) {
861 return EXIT_FAILURE;
862 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200863 goto error;
864 }
Michal Vasko88c29542015-11-27 14:57:53 +0100865 }
866 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200867
Michal Vasko88c29542015-11-27 14:57:53 +0100868 case LY_TYPE_BOOL:
869 case LY_TYPE_EMPTY:
870 /* no sub-statement allowed */
871 LY_TREE_FOR(yin->child, node) {
872 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
873 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200874 goto error;
875 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200876 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200877 break;
878
879 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100880 LOGINT;
881 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200882 }
883
884 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200885
886error:
Michal Vasko88c29542015-11-27 14:57:53 +0100887 return -1;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200888}
889
Michal Vasko0d343d12015-08-24 14:57:36 +0200890/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200892fill_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 +0200893{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200894 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100895 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200896 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100899 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 goto error;
901 }
902 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200904 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +0200905 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200906 goto error;
907 }
Radek Krejcieac35532015-05-31 19:09:15 +0200908
Michal Vasko88c29542015-11-27 14:57:53 +0100909 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200910 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
911 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200912 continue;
913 }
914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200915 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200916 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200917 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200918 goto error;
919 }
Michal Vasko88c29542015-11-27 14:57:53 +0100920 /* HACK for unres */
921 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100922 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100923 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200924 goto error;
925 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200926 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927 } else if (!strcmp(node->name, "default")) {
928 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200929 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 goto error;
931 }
932 GETVAL(value, node, "value");
933 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200934 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 } else if (!strcmp(node->name, "units")) {
936 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200937 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 goto error;
939 }
940 GETVAL(value, node, "name");
941 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
942 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200943 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 goto error;
945 }
946 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200949 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200950 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 goto error;
952 }
Radek Krejcieac35532015-05-31 19:09:15 +0200953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200955 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +0200956 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200957 goto error;
958 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200959 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200961 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200962
963error:
964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200966}
967
Michal Vasko0d343d12015-08-24 14:57:36 +0200968/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +0200969static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200970fill_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 +0200971{
972 const char *value;
973 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +0200974 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +0200975
Radek Krejcib05774c2015-06-18 13:52:59 +0200976 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100977 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +0200978 goto error;
979 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200980 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +0200981 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +0200982
Radek Krejci76512572015-08-04 09:47:08 +0200983 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +0200984 goto error;
985 }
986
987 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200988 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
989 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100990 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 continue;
992 }
993
Radek Krejci3cf9e222015-06-18 11:37:50 +0200994 if (!strcmp(child->name, "if-feature")) {
995 c++;
996 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200997 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +0200998 goto error;
999 }
1000 }
1001
1002 if (c) {
1003 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001004 if (!f->features) {
1005 LOGMEM;
1006 goto error;
1007 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001008 }
Radek Krejci73adb602015-07-02 18:07:40 +02001009 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001010 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001011 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001012 goto error;
1013 }
Radek Krejcicf509982015-12-15 09:22:44 +01001014 /* hack - store pointer to the parent node for later status check */
1015 f->features[f->features_size] = f;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001016 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001017 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001018 f->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001019 lydict_remove(module->ctx, value);
1020 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001021 goto error;
1022 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001023 }
1024
Radek Krejci3cf9e222015-06-18 11:37:50 +02001025 return EXIT_SUCCESS;
1026
1027error:
1028
1029 return EXIT_FAILURE;
1030}
1031
Michal Vasko0d343d12015-08-24 14:57:36 +02001032/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001033static int
Radek Krejcib8048692015-08-05 13:36:34 +02001034fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001035{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001038 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001039 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001040 if (!must->expr) {
1041 goto error;
1042 }
Radek Krejci800af702015-06-02 13:46:01 +02001043
Radek Krejci41726f92015-06-19 13:11:05 +02001044 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001045
Radek Krejci41726f92015-06-19 13:11:05 +02001046error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001049}
1050
Radek Krejci581ce772015-11-10 17:22:40 +01001051static int
Michal Vasko88c29542015-11-27 14:57:53 +01001052fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1053 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001054{
1055 int i, j;
1056 const char *value, *vaux;
1057
1058 /* get unique value (list of leafs supposed to be unique */
1059 GETVAL(value, yin, "tag");
1060
1061 /* count the number of unique leafs in the value */
1062 vaux = value;
1063 while ((vaux = strpbrk(vaux, " \t\n"))) {
1064 unique->expr_size++;
1065 while (isspace(*vaux)) {
1066 vaux++;
1067 }
1068 }
1069 unique->expr_size++;
1070 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001071 if (!unique->expr) {
1072 LOGMEM;
1073 goto error;
1074 }
Radek Krejci581ce772015-11-10 17:22:40 +01001075
1076 for (i = 0; i < unique->expr_size; i++) {
1077 vaux = strpbrk(value, " \t\n");
1078 if (!vaux) {
1079 /* the last token, lydict_insert() will count its size on its own */
1080 vaux = value;
1081 }
1082
1083 /* store token into unique structure */
1084 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1085
1086 /* check that the expression does not repeat */
1087 for (j = 0; j < i; j++) {
1088 if (unique->expr[j] == unique->expr[i]) {
1089 LOGVAL(LYE_INARG, LOGLINE(yin), unique->expr[i], "unique");
1090 LOGVAL(LYE_SPEC, 0, "The identifier is not unique");
1091 goto error;
1092 }
1093 }
1094
1095 /* try to resolve leaf */
1096 if (unres) {
1097 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1098 } else {
1099 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1100 goto error;
1101 }
1102 }
1103
1104 /* move to next token */
1105 value = vaux;
1106 while(isspace(*value)) {
1107 value++;
1108 }
1109 }
1110
1111 return EXIT_SUCCESS;
1112
1113error:
1114 return EXIT_FAILURE;
1115}
1116
Michal Vasko0d343d12015-08-24 14:57:36 +02001117/* logs directly
1118 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001119 * type: 0 - min, 1 - max
1120 */
1121static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001122deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001123{
1124 const char *value;
1125 char *endptr;
1126 unsigned long val;
1127 uint32_t *ui32val;
1128
1129 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001130 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001131 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001132 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001133 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001134 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001135 }
Radek Krejci76512572015-08-04 09:47:08 +02001136 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001137 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001138 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001139 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001140 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001141 }
1142 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001143 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1144 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001145 goto error;
1146 }
1147
1148 GETVAL(value, node, "value");
1149 while (isspace(value[0])) {
1150 value++;
1151 }
1152
1153 /* convert it to uint32_t */
1154 errno = 0;
1155 endptr = NULL;
1156 val = strtoul(value, &endptr, 10);
1157 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001158 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001159 goto error;
1160 }
1161 if (type) {
1162 d->max = (uint32_t)val;
1163 } else {
1164 d->min = (uint32_t)val;
1165 }
1166
1167 if (d->mod == LY_DEVIATE_ADD) {
1168 /* check that there is no current value */
1169 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001170 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1171 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001172 goto error;
1173 }
1174 }
1175
1176 if (d->mod == LY_DEVIATE_DEL) {
1177 /* check values */
1178 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001179 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1180 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001181 goto error;
1182 }
1183 /* remove current min-elements value of the target */
1184 *ui32val = 0;
1185 } else { /* add (already checked) and replace */
1186 /* set new value specified in deviation */
1187 *ui32val = (uint32_t)val;
1188 }
1189
1190 return EXIT_SUCCESS;
1191
1192error:
1193
1194 return EXIT_FAILURE;
1195}
1196
Michal Vasko0d343d12015-08-24 14:57:36 +02001197/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001198static int
Michal Vasko88c29542015-11-27 14:57:53 +01001199fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1200 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001201{
1202 const char *value, **stritem;
1203 struct lyxml_elem *next, *child, *develem;
1204 int c_dev = 0, c_must, c_uniq;
1205 int f_min = 0; /* flags */
Radek Krejci581ce772015-11-10 17:22:40 +01001206 int i, j, k, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001207 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001208 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001209 struct lys_node_choice *choice = NULL;
1210 struct lys_node_leaf *leaf = NULL;
1211 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001212 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001213 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001214 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001215
1216 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001217 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001218 if (!dev->target_name) {
1219 goto error;
1220 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001221
1222 /* resolve target node */
Michal Vasko1e62a092015-12-01 12:27:20 +01001223 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, (const struct lys_node **)&dev->target);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001224 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001225 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001226 goto error;
1227 }
1228 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001229 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001230 goto error;
1231 }
1232 /* mark the target module as deviated */
1233 dev->target->module->deviated = 1;
1234
1235 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001236 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1237 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001238 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001239 continue;
1240 }
1241
Radek Krejcieb00f512015-07-01 16:44:58 +02001242 if (!strcmp(child->name, "description")) {
1243 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001244 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001245 goto error;
1246 }
1247 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1248 if (!dev->dsc) {
1249 goto error;
1250 }
1251 } else if (!strcmp(child->name, "reference")) {
1252 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001253 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001254 goto error;
1255 }
1256 dev->ref = read_yin_subnode(module->ctx, child, "text");
1257 if (!dev->ref) {
1258 goto error;
1259 }
1260 } else if (!strcmp(child->name, "deviate")) {
1261 c_dev++;
1262
Michal Vasko345da0a2015-12-02 10:35:55 +01001263 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001264 * further processed later
1265 */
1266 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001267
Radek Krejcieb00f512015-07-01 16:44:58 +02001268 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001269 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001270 goto error;
1271 }
1272
Michal Vasko345da0a2015-12-02 10:35:55 +01001273 lyxml_free(module->ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001274 }
1275
1276 if (c_dev) {
1277 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001278 if (!dev->deviate) {
1279 LOGMEM;
1280 goto error;
1281 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001282 }
1283
1284 LY_TREE_FOR(yin->child, develem) {
1285 /* init */
1286 f_min = 0;
1287 c_must = 0;
1288 c_uniq = 0;
1289
1290 /* get deviation type */
1291 GETVAL(value, develem, "value");
1292 if (!strcmp(value, "not-supported")) {
1293 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1294 /* no property expected in this case */
1295 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001296 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001297 goto error;
1298 }
1299
Radek Krejci5b917642015-07-02 09:03:13 +02001300 /* and neither any other deviate statement is expected,
1301 * not-supported deviation must be the only deviation of the target
1302 */
1303 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001304 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1305 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001306 goto error;
1307 }
1308
1309
Radek Krejcieb00f512015-07-01 16:44:58 +02001310 /* remove target node */
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001311 lys_node_free(dev->target, NULL);
Radek Krejci5b917642015-07-02 09:03:13 +02001312 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001313
Radek Krejci5b917642015-07-02 09:03:13 +02001314 dev->deviate_size = 1;
1315 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001316 } else if (!strcmp(value, "add")) {
1317 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1318 } else if (!strcmp(value, "replace")) {
1319 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1320 } else if (!strcmp(value, "delete")) {
1321 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1322 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001323 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001324 goto error;
1325 }
1326 d = &dev->deviate[dev->deviate_size];
1327
1328 /* process deviation properties */
1329 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001330 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1331 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001332 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001333 continue;
1334 }
1335
Radek Krejcieb00f512015-07-01 16:44:58 +02001336 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001337 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001338 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001339 goto error;
1340 }
1341
1342 /* for we deviate from RFC 6020 and allow config property even it is/is not
1343 * specified in the target explicitly since config property inherits. So we expect
1344 * that config is specified in every node. But for delete, we check that the value
1345 * is the same as here in deviation
1346 */
1347 GETVAL(value, child, "value");
1348 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001349 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001350 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001351 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001352 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001353 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001354 goto error;
1355 }
1356
1357 if (d->mod == LY_DEVIATE_DEL) {
1358 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001359 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001360 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1361 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001362 goto error;
1363 }
1364 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001365 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001366
1367 /* ... and inherit config value from the target's parent */
1368 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001369 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001370 } else {
1371 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001372 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 }
1374 } else { /* add and replace are the same in this case */
1375 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001376 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001377
1378 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001379 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001380 }
1381 } else if (!strcmp(child->name, "default")) {
1382 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001383 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001384 goto error;
1385 }
1386 GETVAL(value, child, "value");
1387 d->dflt = lydict_insert(module->ctx, value, 0);
1388
Radek Krejci76512572015-08-04 09:47:08 +02001389 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001390 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001391
1392 if (d->mod == LY_DEVIATE_ADD) {
1393 /* check that there is no current value */
1394 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001395 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1396 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001397 goto error;
1398 }
1399 }
1400
Michal Vasko1e62a092015-12-01 12:27:20 +01001401 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE,
1402 (const struct lys_node **)&node);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001403 if (rc) {
1404 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1405 goto error;
1406 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001407 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001408 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001409 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1410 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001411 goto error;
1412 }
1413 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001414 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415 if (!choice->dflt) {
1416 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001417 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 goto error;
1419 }
1420 }
Radek Krejci76512572015-08-04 09:47:08 +02001421 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001422 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001423
1424 if (d->mod == LY_DEVIATE_ADD) {
1425 /* check that there is no current value */
1426 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001427 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1428 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001429 goto error;
1430 }
1431 }
1432
1433 if (d->mod == LY_DEVIATE_DEL) {
1434 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001435 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1436 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001437 goto error;
1438 }
1439 /* remove value */
1440 lydict_remove(leaf->module->ctx, leaf->dflt);
1441 leaf->dflt = NULL;
1442 } else { /* add (already checked) and replace */
1443 /* remove value */
1444 lydict_remove(leaf->module->ctx, leaf->dflt);
1445
1446 /* set new value */
1447 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1448 }
1449 } else {
1450 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001451 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1452 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001453 goto error;
1454 }
1455 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001456 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001457 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001458 goto error;
1459 }
1460
1461 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001462 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001463 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1464 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001465 goto error;
1466 }
1467
1468 GETVAL(value, child, "value");
1469 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001470 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001472 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001473 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001474 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001475 goto error;
1476 }
1477
1478 if (d->mod == LY_DEVIATE_ADD) {
1479 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001480 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001481 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1482 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001483 goto error;
1484 }
1485 }
1486
1487 if (d->mod == LY_DEVIATE_DEL) {
1488 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001489 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001490 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1491 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001492 goto error;
1493 }
1494 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001495 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001496 } else { /* add (already checked) and replace */
1497 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001498 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001499
1500 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001501 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 }
1503 } else if (!strcmp(child->name, "min-elements")) {
1504 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001505 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001506 goto error;
1507 }
1508 f_min = 1;
1509
1510 if (deviate_minmax(dev->target, child, d, 0)) {
1511 goto error;
1512 }
1513 } else if (!strcmp(child->name, "max-elements")) {
1514 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001515 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001516 goto error;
1517 }
1518
1519 if (deviate_minmax(dev->target, child, d, 1)) {
1520 goto error;
1521 }
1522 } else if (!strcmp(child->name, "must")) {
1523 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001524 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001525 continue;
1526 } else if (!strcmp(child->name, "type")) {
1527 if (d->type) {
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 }
1531
1532 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001533 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001534 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001535 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001536 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001537 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001538 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1539 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001540 goto error;
1541 }
1542
1543 if (d->mod == LY_DEVIATE_ADD) {
1544 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001545 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1546 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001547 goto error;
1548 } else if (d->mod == LY_DEVIATE_DEL) {
1549 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001550 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1551 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001552 goto error;
1553 }
1554
1555 /* replace */
1556 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001557 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001558
1559 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001560 /* HACK for unres */
1561 t->der = (struct lys_tpdf *)child;
1562 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev->target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 goto error;
1564 }
1565 d->type = t;
1566 } else if (!strcmp(child->name, "unique")) {
1567 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001568 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001569 continue;
1570 } else if (!strcmp(child->name, "units")) {
1571 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001572 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001573 goto error;
1574 }
1575
1576 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001577 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001578 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001579 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001580 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001581 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001582 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1583 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001584 goto error;
1585 }
1586
1587 /* get units value */
1588 GETVAL(value, child, "name");
1589 d->units = lydict_insert(module->ctx, value, 0);
1590
1591 /* apply to target */
1592 if (d->mod == LY_DEVIATE_ADD) {
1593 /* check that there is no current value */
1594 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001595 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1596 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001597 goto error;
1598 }
1599 }
1600
1601 if (d->mod == LY_DEVIATE_DEL) {
1602 /* check values */
1603 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001604 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1605 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 goto error;
1607 }
1608 /* remove current units value of the target */
1609 lydict_remove(dev->target->module->ctx, *stritem);
1610 } else { /* add (already checked) and replace */
1611 /* remove current units value of the target ... */
1612 lydict_remove(dev->target->module->ctx, *stritem);
1613
1614 /* ... and replace it with the value specified in deviation */
1615 *stritem = lydict_insert(module->ctx, value, 0);
1616 }
1617 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001618 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001619 goto error;
1620 }
1621
Michal Vasko88c29542015-11-27 14:57:53 +01001622 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001623 }
1624
1625 if (c_must) {
1626 /* check target node type */
1627 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001628 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001629 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1630 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001631 break;
Radek Krejci76512572015-08-04 09:47:08 +02001632 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001633 trg_must = &((struct lys_node_container *)dev->target)->must;
1634 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 break;
Radek Krejci76512572015-08-04 09:47:08 +02001636 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001637 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1638 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001639 break;
Radek Krejci76512572015-08-04 09:47:08 +02001640 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001641 trg_must = &((struct lys_node_list *)dev->target)->must;
1642 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001643 break;
Radek Krejci76512572015-08-04 09:47:08 +02001644 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001645 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1646 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 break;
1648 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001649 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1650 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001651 goto error;
1652 }
1653
1654 if (d->mod == LY_DEVIATE_RPL) {
1655 /* remove target's musts and allocate new array for it */
1656 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001657 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1658 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001659 goto error;
1660 }
1661
1662 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001663 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001664 }
1665 free(*trg_must);
1666 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1667 d->must_size = c_must;
1668 *trg_must_size = 0;
1669 } else if (d->mod == LY_DEVIATE_ADD) {
1670 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001671 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02001672 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001673 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001674 d->must_size = c_must;
1675 } else { /* LY_DEVIATE_DEL */
1676 d->must = calloc(c_must, sizeof *d->must);
1677 }
Michal Vasko253035f2015-12-17 16:58:13 +01001678 if (!d->must) {
1679 LOGMEM;
1680 goto error;
1681 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 }
1683 if (c_uniq) {
1684 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001685 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001686 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1687 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001688 goto error;
1689 }
1690
Radek Krejcib8048692015-08-05 13:36:34 +02001691 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 if (d->mod == LY_DEVIATE_RPL) {
1693 /* remove target's unique and allocate new array for it */
1694 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001695 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1696 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 goto error;
1698 }
1699
1700 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001701 for (j = 0; j < list->unique[i].expr_size; j++) {
1702 lydict_remove(list->module->ctx, list->unique[i].expr[j]);
1703 }
1704 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001705 }
1706 free(list->unique);
1707 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1708 d->unique_size = c_uniq;
1709 list->unique_size = 0;
1710 } else if (d->mod == LY_DEVIATE_ADD) {
1711 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001712 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 list->unique = d->unique;
1714 d->unique = &list->unique[list->unique_size];
1715 d->unique_size = c_uniq;
1716 } else { /* LY_DEVIATE_DEL */
1717 d->unique = calloc(c_uniq, sizeof *d->unique);
1718 }
Michal Vasko253035f2015-12-17 16:58:13 +01001719 if (!d->unique) {
1720 LOGMEM;
1721 goto error;
1722 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001723 }
1724
1725 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001726 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 if (!strcmp(child->name, "must")) {
1728 if (d->mod == LY_DEVIATE_DEL) {
1729 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1730 goto error;
1731 }
1732
1733 /* find must to delete, we are ok with just matching conditions */
1734 for (i = 0; i < *trg_must_size; i++) {
1735 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1736 /* we have a match, free the must structure ... */
Michal Vasko5e7d9ca2015-10-23 10:37:28 +02001737 lys_restr_free(dev->target->module->ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 /* ... and maintain the array */
1739 (*trg_must_size)--;
1740 if (i != *trg_must_size) {
1741 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1742 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1743 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1744 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1745 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1746 }
1747 if (!(*trg_must_size)) {
1748 free(*trg_must);
1749 *trg_must = NULL;
1750 } else {
1751 (*trg_must)[*trg_must_size].expr = NULL;
1752 (*trg_must)[*trg_must_size].dsc = NULL;
1753 (*trg_must)[*trg_must_size].ref = NULL;
1754 (*trg_must)[*trg_must_size].eapptag = NULL;
1755 (*trg_must)[*trg_must_size].emsg = NULL;
1756 }
1757
1758 i = -1; /* set match flag */
1759 break;
1760 }
1761 }
1762 d->must_size++;
1763 if (i != -1) {
1764 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001765 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1766 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001767 goto error;
1768 }
1769 } else { /* replace or add */
1770 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1771 goto error;
1772 }
1773 (*trg_must_size)++;
1774 }
1775 } else if (!strcmp(child->name, "unique")) {
1776 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci581ce772015-11-10 17:22:40 +01001777 if (fill_yin_unique(module, dev->target, child, &d->unique[d->unique_size], NULL)) {
1778 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 goto error;
1780 }
1781
1782 /* find unique structures to delete */
1783 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001784 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001785 continue;
1786 }
1787
Radek Krejci581ce772015-11-10 17:22:40 +01001788 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1789 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 break;
1791 }
1792 }
1793
Radek Krejci581ce772015-11-10 17:22:40 +01001794 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001796 for (j = 0; j < list->unique[i].expr_size; j++) {
1797 lydict_remove(list->module->ctx, list->unique[i].expr[j]);
1798 }
1799 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001800 /* ... and maintain the array */
1801 list->unique_size--;
1802 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001803 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1804 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001805 }
1806
1807 if (!list->unique_size) {
1808 free(list->unique);
1809 list->unique = NULL;
1810 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001811 list->unique[list->unique_size].expr_size = 0;
1812 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001813 }
1814
1815 i = -1; /* set match flag */
1816 break;
1817 }
1818 }
1819
1820 d->unique_size++;
1821 if (i != -1) {
1822 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001823 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1824 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 goto error;
1826 }
1827 } else { /* replace or add */
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001828 i = fill_yin_unique(module, dev->target, child, &list->unique[list->unique_size], NULL);
1829 list->unique_size++;
1830 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001831 goto error;
1832 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001833 }
1834 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001835 }
Radek Krejci5b917642015-07-02 09:03:13 +02001836
1837 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001838 }
1839
Radek Krejcieb00f512015-07-01 16:44:58 +02001840 return EXIT_SUCCESS;
1841
1842error:
1843
1844 if (dev->deviate) {
1845 for (i = 0; i < dev->deviate_size; i++) {
1846 lydict_remove(module->ctx, dev->deviate[i].dflt);
1847 lydict_remove(module->ctx, dev->deviate[i].units);
1848
1849 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1850 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001851 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 }
1853 free(dev->deviate[i].must);
1854
1855 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001856 for (k = 0; k < dev->deviate[i].unique[i].expr_size; k++) {
1857 lydict_remove(module->ctx, dev->deviate[i].unique[j].expr[k]);
1858 }
1859 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001860 }
1861 free(dev->deviate[i].unique);
1862 }
1863 }
1864 free(dev->deviate);
1865 }
1866
1867 return EXIT_FAILURE;
1868}
1869
Michal Vasko0d343d12015-08-24 14:57:36 +02001870/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001871static int
Radek Krejcib8048692015-08-05 13:36:34 +02001872fill_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 +02001873 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001874{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001876 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001877 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001878 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001879
Michal Vasko591e0b22015-08-13 13:53:43 +02001880 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001882 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001883 if (!aug->target_name) {
1884 goto error;
1885 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001886 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001887
Michal Vasko1d87a922015-08-21 12:57:16 +02001888 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001889 goto error;
1890 }
1891
1892 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001893 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1894 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001895 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001896 continue;
1897 }
1898
Radek Krejci3cf9e222015-06-18 11:37:50 +02001899 if (!strcmp(child->name, "if-feature")) {
1900 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001901 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001902 } else if (!strcmp(child->name, "when")) {
1903 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001904 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001905 goto error;
1906 }
1907
1908 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001909 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001910 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001911 goto error;
1912 }
Michal Vaskofcdac172015-10-07 09:35:05 +02001913 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001914 goto error;
1915 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001916 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001917 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001918
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001919 /* check allowed data sub-statements */
1920 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001921 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001923 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001924 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001925 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001926 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001927 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001928 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001929 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001930 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001931 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001932 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001934 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001935 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001936 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001937 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001938 goto error;
1939 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001940
Radek Krejci1d82ef62015-08-07 14:44:40 +02001941 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001942 goto error;
1943 }
1944
1945 /* check for mandatory nodes - if the target node is in another module
1946 * the added nodes cannot be mandatory
1947 */
Radek Krejcic6556022016-01-27 15:16:45 +01001948 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001949 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001950 goto error;
1951 }
1952
Radek Krejci1d82ef62015-08-07 14:44:40 +02001953 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001954 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001955 }
1956
1957 if (c) {
1958 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001959 if (!aug->features) {
1960 LOGMEM;
1961 goto error;
1962 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001963 }
1964
1965 LY_TREE_FOR_SAFE(yin->child, next, child) {
1966 if (!strcmp(child->name, "if-feature")) {
1967 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001968 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001969 goto error;
1970 }
Radek Krejcicf509982015-12-15 09:22:44 +01001971 /* hack - store pointer to the parent node for later status check */
1972 aug->features[aug->features_size] = (struct lys_feature *)aug;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001973 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001974 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001975 aug->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001976 lydict_remove(module->ctx, value);
1977 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001978 goto error;
1979 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001980 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001981 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001982 }
1983
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001984 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02001985 * connected to the tree and adjusted (if possible right now).
1986 * However, if this is augment in a uses, it gets resolved
1987 * when the uses does and cannot be resolved now for sure
1988 * (the grouping was not yet copied into uses).
1989 */
1990 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02001991 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02001992 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
1993 goto error;
1994 }
Michal Vasko49291b32015-08-06 09:49:41 +02001995 }
Radek Krejci106efc02015-06-10 14:36:27 +02001996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02001998
1999error:
2000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002001 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002002}
2003
Michal Vasko0d343d12015-08-24 14:57:36 +02002004/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005static int
Michal Vasko0d204592015-10-07 09:50:04 +02002006fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002007{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008 struct lyxml_elem *sub, *next;
2009 const char *value;
2010 char *endptr;
2011 int f_mand = 0, f_min = 0, f_max = 0;
2012 int c_must = 0;
2013 int r;
2014 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002015
Radek Krejci76512572015-08-04 09:47:08 +02002016 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002017 goto error;
2018 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002019
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002020 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002021 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002022 if (!rfn->target_name) {
2023 goto error;
2024 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002027 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2028 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002029 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002030 continue;
2031 }
2032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 /* limited applicability */
2034 if (!strcmp(sub->name, "default")) {
2035 /* leaf or choice */
2036 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002037 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 goto error;
2039 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 /* check possibility of statements combination */
2042 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002043 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002044 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002045 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 goto error;
2047 }
2048 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002049 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002050 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 GETVAL(value, sub, "value");
2053 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2054 } else if (!strcmp(sub->name, "mandatory")) {
2055 /* leaf, choice or anyxml */
2056 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002057 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 goto error;
2059 }
2060 /* just checking the flags in leaf is not sufficient, we would allow
2061 * multiple mandatory statements with the "false" value
2062 */
2063 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 /* check possibility of statements combination */
2066 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002067 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002069 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 goto error;
2071 }
2072 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002073 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 GETVAL(value, sub, "value");
2077 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002078 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002080 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002082 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 goto error;
2084 }
2085 } else if (!strcmp(sub->name, "min-elements")) {
2086 /* list or leaf-list */
2087 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002088 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 goto error;
2090 }
2091 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 /* check possibility of statements combination */
2094 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002095 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002097 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 goto error;
2099 }
2100 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002101 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 GETVAL(value, sub, "value");
2105 while (isspace(value[0])) {
2106 value++;
2107 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 /* convert it to uint32_t */
2110 errno = 0;
2111 endptr = NULL;
2112 val = strtoul(value, &endptr, 10);
2113 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002114 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 goto error;
2116 }
2117 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 /* magic - bit 3 in flags means min set */
2120 rfn->flags |= 0x04;
2121 } else if (!strcmp(sub->name, "max-elements")) {
2122 /* list or leaf-list */
2123 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002124 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 goto error;
2126 }
2127 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 /* check possibility of statements combination */
2130 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002131 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002133 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 goto error;
2135 }
2136 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002137 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 GETVAL(value, sub, "value");
2141 while (isspace(value[0])) {
2142 value++;
2143 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 /* convert it to uint32_t */
2146 errno = 0;
2147 endptr = NULL;
2148 val = strtoul(value, &endptr, 10);
2149 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002150 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 goto error;
2152 }
2153 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 /* magic - bit 4 in flags means min set */
2156 rfn->flags |= 0x08;
2157 } else if (!strcmp(sub->name, "presence")) {
2158 /* container */
2159 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002160 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 goto error;
2162 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 /* check possibility of statements combination */
2165 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002166 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002168 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 goto error;
2170 }
2171 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002172 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 GETVAL(value, sub, "value");
2176 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2177 } else if (!strcmp(sub->name, "must")) {
2178 /* leaf-list, list, container or anyxml */
2179 /* check possibility of statements combination */
2180 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002181 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002183 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 goto error;
2185 }
2186 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002187 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002191 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002194 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 goto error;
2196 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002197
Michal Vasko345da0a2015-12-02 10:35:55 +01002198 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 /* process nodes with cardinality of 0..n */
2202 if (c_must) {
2203 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002204 if (!rfn->must) {
2205 LOGMEM;
2206 goto error;
2207 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 }
Radek Krejci73adb602015-07-02 18:07:40 +02002209 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002210 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2211 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002212 if (r) {
2213 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 }
Michal Vasko0d204592015-10-07 09:50:04 +02002215 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002216 goto error;
2217 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002221
2222error:
2223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002225}
2226
Michal Vasko0d343d12015-08-24 14:57:36 +02002227/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228static int
Radek Krejcib8048692015-08-05 13:36:34 +02002229fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002230{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 struct lyxml_elem *child;
2232 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002233 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002236 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2237 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002238 continue;
2239 }
2240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 if (!strcmp(child->name, "prefix")) {
2242 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002243 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 goto error;
2245 }
2246 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2247 } else if (!strcmp(child->name, "revision-date")) {
2248 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002249 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 goto error;
2251 }
2252 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002253 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 goto error;
2255 }
2256 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2257 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002258 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 goto error;
2260 }
2261 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 /* check mandatory information */
2264 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002265 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 goto error;
2267 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002270
2271 /* check for circular import, store it if passed */
2272 if (!module->ctx->models.parsing) {
2273 count = 0;
2274 } else {
2275 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2276 if (value == module->ctx->models.parsing[count]) {
2277 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2278 goto error;
2279 }
2280 }
2281 }
2282 ++count;
2283 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002284 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2285 if (!module->ctx->models.parsing) {
2286 LOGMEM;
2287 goto error;
2288 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002289 module->ctx->models.parsing[count - 1] = value;
2290 module->ctx->models.parsing[count] = NULL;
2291
2292 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002293 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 +02002294 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002295 /* whether to use a user callback is decided in the function */
2296 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 +02002297 }
2298
2299 /* remove the new module name now that its parsing is finished (even if failed) */
2300 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2301 LOGINT;
2302 }
2303 --count;
2304 if (count) {
2305 module->ctx->models.parsing[count] = NULL;
2306 } else {
2307 free(module->ctx->models.parsing);
2308 module->ctx->models.parsing = NULL;
2309 }
2310
2311 /* check the result */
2312 if (!imp->module) {
2313 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2314 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2315 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002319
2320error:
2321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002323}
2324
Michal Vasko0d343d12015-08-24 14:57:36 +02002325/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326static int
Radek Krejcic071c542016-01-27 14:57:51 +01002327fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +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 Vasko1b882eb2015-10-22 11:43:14 +02002334 int count;
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
2359 /* check for circular include, store it if passed */
2360 if (!module->ctx->models.parsing) {
2361 count = 0;
2362 } else {
2363 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2364 if (value == module->ctx->models.parsing[count]) {
2365 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2366 goto error;
2367 }
2368 }
2369 }
2370 ++count;
2371 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002372 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2373 if (!module->ctx->models.parsing) {
2374 LOGMEM;
2375 goto error;
2376 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002377 module->ctx->models.parsing[count - 1] = value;
2378 module->ctx->models.parsing[count] = NULL;
2379
2380 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002381 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002382 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002383 if (module->ctx->module_clb) {
2384 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2385 &format, &module_data_free);
2386 if (module_data) {
Radek Krejcic071c542016-01-27 14:57:51 +01002387 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002388 if (module_data_free) {
2389 module_data_free(module_data);
2390 } else {
2391 free(module_data);
2392 }
2393 } else {
2394 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2395 }
2396 } else {
2397 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
Radek Krejcic071c542016-01-27 14:57:51 +01002398 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002399 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002400 }
2401
2402 /* remove the new submodule name now that its parsing is finished (even if failed) */
2403 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2404 LOGINT;
2405 }
2406 --count;
2407 if (count) {
2408 module->ctx->models.parsing[count] = NULL;
2409 } else {
2410 free(module->ctx->models.parsing);
2411 module->ctx->models.parsing = NULL;
2412 }
2413
2414 /* check the result */
2415 if (!inc->submodule) {
2416 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2417 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2418 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002422
2423error:
2424
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002426}
2427
Michal Vasko0d343d12015-08-24 14:57:36 +02002428/* logs directly
2429 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002430 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002431 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002432 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002433 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002434static int
Radek Krejcib8048692015-08-05 13:36:34 +02002435read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002436 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002437{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 const char *value;
2439 struct lyxml_elem *sub, *next;
2440 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002443 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002444 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 if (opt & OPT_IDENT) {
2447 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002448 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 goto error;
2450 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002451 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002453
Radek Krejci6764bb32015-07-03 15:16:04 +02002454 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002455 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002456 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002457 }
2458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 /* process local parameters */
2460 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002461 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002462 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002463 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002464 continue;
2465 }
2466 if (strcmp(sub->ns->value, LY_NSYIN)) {
2467 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002468 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002469 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002470 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002471 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002472 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002473 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002474 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002475 goto error;
2476 }
2477 }
2478
2479 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002480 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002481 continue;
2482 }
2483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002486 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 goto error;
2488 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002489 node->dsc = read_yin_subnode(ctx, sub, "text");
2490 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002491 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 }
2493 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002494 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002495 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 goto error;
2497 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002498 node->ref = read_yin_subnode(ctx, sub, "text");
2499 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002500 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 }
2502 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002503 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002504 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 goto error;
2506 }
2507 GETVAL(value, sub, "value");
2508 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002509 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002511 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002512 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002513 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002514 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002515 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002516 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002517 }
2518 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002519 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002520 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002521 goto error;
2522 }
2523 GETVAL(value, sub, "value");
2524 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002525 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002527 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002528 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002529 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002530 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 }
2532 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002533 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 continue;
2535 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002536 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002538
Radek Krejci1d82ef62015-08-07 14:44:40 +02002539 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 /* get config flag from parent */
2541 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002542 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002543 } else {
2544 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002545 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 }
2547 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002549 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002550
2551error:
2552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002554}
2555
Michal Vasko0d343d12015-08-24 14:57:36 +02002556/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002557static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002558read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002559{
Radek Krejci76512572015-08-04 09:47:08 +02002560 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002561 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002562 const char *value;
2563
2564 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002565 if (!retval) {
2566 LOGMEM;
2567 return NULL;
2568 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002569
2570 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002571 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002572 if (!retval->cond) {
2573 goto error;
2574 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002575
Radek Krejci73adb602015-07-02 18:07:40 +02002576 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002577 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2578 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002579 continue;
2580 }
2581
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002582 if (!strcmp(child->name, "description")) {
2583 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002584 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002585 goto error;
2586 }
2587 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2588 if (!retval->dsc) {
2589 goto error;
2590 }
2591 } else if (!strcmp(child->name, "reference")) {
2592 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002593 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002594 goto error;
2595 }
2596 retval->ref = read_yin_subnode(module->ctx, child, "text");
2597 if (!retval->ref) {
2598 goto error;
2599 }
2600 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002601 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002602 goto error;
2603 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002604 }
2605
2606 return retval;
2607
2608error:
2609
Michal Vasko0308dd62015-10-07 09:14:40 +02002610 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002611 return NULL;
2612}
2613
Michal Vasko0d343d12015-08-24 14:57:36 +02002614/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002615static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002616read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2617 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002618{
Michal Vasko29fc0182015-08-24 15:02:39 +02002619 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002620 struct lys_node_case *cs;
2621 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002622 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002623 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002624
Radek Krejcie867c852015-08-27 09:52:34 +02002625 /* init */
2626 memset(&root, 0, sizeof root);
2627
Radek Krejci1d82ef62015-08-07 14:44:40 +02002628 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002629 if (!cs) {
2630 LOGMEM;
2631 return NULL;
2632 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002633 cs->nodetype = LYS_CASE;
2634 cs->prev = (struct lys_node *)cs;
2635 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002636
Radek Krejci6a113852015-07-03 16:04:20 +02002637 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 goto error;
2639 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002640
Radek Krejcia9544502015-08-14 08:24:29 +02002641 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2642
Michal Vasko3a0043f2015-08-12 12:11:30 +02002643 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002644 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002645 goto error;
2646 }
2647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 /* process choice's specific children */
2649 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002650 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2651 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002652 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002653 continue;
2654 }
2655
Michal Vasko29fc0182015-08-24 15:02:39 +02002656 if (!strcmp(sub->name, "container") ||
2657 !strcmp(sub->name, "leaf-list") ||
2658 !strcmp(sub->name, "leaf") ||
2659 !strcmp(sub->name, "list") ||
2660 !strcmp(sub->name, "uses") ||
2661 !strcmp(sub->name, "choice") ||
2662 !strcmp(sub->name, "anyxml")) {
2663
Michal Vaskof3930de2015-10-22 12:03:59 +02002664 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002665 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002666 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002667 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002668 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002669 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002670 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002671 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002672 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002673 goto error;
2674 }
2675
Radek Krejci1d82ef62015-08-07 14:44:40 +02002676 cs->when = read_yin_when(module, sub);
2677 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002678 goto error;
2679 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002680 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002681 goto error;
2682 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002683
Michal Vasko345da0a2015-12-02 10:35:55 +01002684 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002685 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002686 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002687 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002689 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002690
Radek Krejci3cf9e222015-06-18 11:37:50 +02002691 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002692 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002693 if (!cs->features) {
2694 LOGMEM;
2695 goto error;
2696 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002697 }
Radek Krejci73adb602015-07-02 18:07:40 +02002698 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002699 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002700 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002701 goto error;
2702 }
Radek Krejcicf509982015-12-15 09:22:44 +01002703 /* hack - store pointer to the parent node for later status check */
2704 cs->features[cs->features_size] = (struct lys_feature *)cs;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002705 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002706 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002707 cs->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002708 lydict_remove(module->ctx, value);
2709 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002710 goto error;
2711 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 }
Radek Krejcib388c152015-06-04 17:03:03 +02002713
Michal Vasko29fc0182015-08-24 15:02:39 +02002714 /* last part - process data nodes */
2715 LY_TREE_FOR_SAFE(root.child, next, sub) {
2716 if (!strcmp(sub->name, "container")) {
2717 node = read_yin_container(module, retval, sub, resolve, unres);
2718 } else if (!strcmp(sub->name, "leaf-list")) {
2719 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2720 } else if (!strcmp(sub->name, "leaf")) {
2721 node = read_yin_leaf(module, retval, sub, resolve, unres);
2722 } else if (!strcmp(sub->name, "list")) {
2723 node = read_yin_list(module, retval, sub, resolve, unres);
2724 } else if (!strcmp(sub->name, "choice")) {
2725 node = read_yin_choice(module, retval, sub, resolve, unres);
2726 } else if (!strcmp(sub->name, "uses")) {
2727 node = read_yin_uses(module, retval, sub, resolve, unres);
2728 } else if (!strcmp(sub->name, "anyxml")) {
2729 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2730 }
2731 if (!node) {
2732 goto error;
2733 }
2734
Michal Vasko345da0a2015-12-02 10:35:55 +01002735 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002736 }
2737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002739
2740error:
2741
Michal Vasko29fc0182015-08-24 15:02:39 +02002742 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002743 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002744 }
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002745 lys_node_free(retval, NULL);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002747 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002748}
2749
Michal Vasko0d343d12015-08-24 14:57:36 +02002750/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002751static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002752read_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 +02002753{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002754 struct lyxml_elem *sub, *next;
2755 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002756 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002757 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002758 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002759 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002762 if (!choice) {
2763 LOGMEM;
2764 return NULL;
2765 }
Radek Krejci76512572015-08-04 09:47:08 +02002766 choice->nodetype = LYS_CHOICE;
2767 choice->prev = (struct lys_node *)choice;
2768 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002769
Michal Vaskoe0c59842015-09-24 13:52:20 +02002770 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2771 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 goto error;
2773 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002774
Radek Krejcia9544502015-08-14 08:24:29 +02002775 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2776
Michal Vasko3a0043f2015-08-12 12:11:30 +02002777 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002778 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002779 goto error;
2780 }
2781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 /* process choice's specific children */
2783 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002784 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2785 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002786 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002787 continue;
2788 }
2789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002790 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002791 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 goto error;
2793 }
2794 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002795 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002796 goto error;
2797 }
2798 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002799 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 goto error;
2801 }
2802 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002803 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002804 goto error;
2805 }
2806 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002807 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002808 goto error;
2809 }
2810 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002811 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 goto error;
2813 }
2814 } else if (!strcmp(sub->name, "default")) {
2815 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002816 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002817 goto error;
2818 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002819 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002820 } else if (!strcmp(sub->name, "mandatory")) {
2821 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002822 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 goto error;
2824 }
2825 /* just checking the flags in leaf is not sufficient, we would allow
2826 * multiple mandatory statements with the "false" value
2827 */
2828 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 GETVAL(value, sub, "value");
2831 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002832 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002833 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002834 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002835 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002836 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 goto error;
2838 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002839 } else if (!strcmp(sub->name, "when")) {
2840 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002841 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002842 goto error;
2843 }
2844
2845 choice->when = read_yin_when(module, sub);
2846 if (!choice->when) {
2847 goto error;
2848 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002849 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002850 goto error;
2851 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002852 } else if (!strcmp(sub->name, "if-feature")) {
2853 c_ftrs++;
2854
Michal Vasko345da0a2015-12-02 10:35:55 +01002855 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002856 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002858 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002859 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002861
Radek Krejci1d82ef62015-08-07 14:44:40 +02002862 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002863 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002864 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002865
Radek Krejci3cf9e222015-06-18 11:37:50 +02002866 if (c_ftrs) {
2867 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002868 if (!choice->features) {
2869 LOGMEM;
2870 goto error;
2871 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002872 }
2873
Radek Krejci73adb602015-07-02 18:07:40 +02002874 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002875 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002876 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002877 goto error;
2878 }
Radek Krejcicf509982015-12-15 09:22:44 +01002879 /* hack - store pointer to the parent node for later status check */
2880 choice->features[choice->features_size] = (struct lys_feature *)choice;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002881 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002882 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002883 choice->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002884 lydict_remove(module->ctx, value);
2885 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002886 goto error;
2887 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002888 }
2889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002891 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002892 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2894 goto error;
2895 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 /* link default with the case */
2898 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002899 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002900 goto error;
2901 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002904 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002905
2906error:
2907
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002908 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002911}
2912
Michal Vasko0d343d12015-08-24 14:57:36 +02002913/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002914static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002915read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002916 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002917{
Radek Krejci76512572015-08-04 09:47:08 +02002918 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002919 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 struct lyxml_elem *sub, *next;
2921 const char *value;
2922 int r;
2923 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002924 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002927 if (!anyxml) {
2928 LOGMEM;
2929 return NULL;
2930 }
Radek Krejci76512572015-08-04 09:47:08 +02002931 anyxml->nodetype = LYS_ANYXML;
2932 anyxml->prev = (struct lys_node *)anyxml;
2933 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002934
Michal Vaskoe0c59842015-09-24 13:52:20 +02002935 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2936 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 goto error;
2938 }
Radek Krejci863c2852015-06-03 15:47:11 +02002939
Radek Krejcia9544502015-08-14 08:24:29 +02002940 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002941
Radek Krejcic071c542016-01-27 14:57:51 +01002942 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002943 goto error;
2944 }
2945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002947 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2948 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002949 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002950 continue;
2951 }
2952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002953 if (!strcmp(sub->name, "mandatory")) {
2954 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002955 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 goto error;
2957 }
2958 /* just checking the flags in leaf is not sufficient, we would allow
2959 * multiple mandatory statements with the "false" value
2960 */
2961 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 GETVAL(value, sub, "value");
2964 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002965 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002966 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002967 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002968 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002969 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002970 goto error;
2971 }
2972 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002973 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002974 } else if (!strcmp(sub->name, "when")) {
2975 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002976 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002977 goto error;
2978 }
2979
2980 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002981 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002982 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002983 goto error;
2984 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002985 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002986 goto error;
2987 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002988 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002989 } else if (!strcmp(sub->name, "must")) {
2990 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002991 } else if (!strcmp(sub->name, "if-feature")) {
2992 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002995 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 }
2998 }
Radek Krejci863c2852015-06-03 15:47:11 +02002999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 /* middle part - process nodes with cardinality of 0..n */
3001 if (c_must) {
3002 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003003 if (!anyxml->must) {
3004 LOGMEM;
3005 goto error;
3006 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003008 if (c_ftrs) {
3009 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003010 if (!anyxml->features) {
3011 LOGMEM;
3012 goto error;
3013 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003014 }
Radek Krejci863c2852015-06-03 15:47:11 +02003015
Radek Krejci73adb602015-07-02 18:07:40 +02003016 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003018 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3019 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 if (r) {
3021 goto error;
3022 }
Michal Vasko0d204592015-10-07 09:50:04 +02003023 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003024 goto error;
3025 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003026 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003027 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003028 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003029 goto error;
3030 }
Radek Krejcicf509982015-12-15 09:22:44 +01003031 /* hack - store pointer to the parent node for later status check */
3032 anyxml->features[anyxml->features_size] = (struct lys_feature *)anyxml;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003033 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003034 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003035 anyxml->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003036 lydict_remove(module->ctx, value);
3037 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003038 goto error;
3039 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003040 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 }
Radek Krejci863c2852015-06-03 15:47:11 +02003042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003044
3045error:
3046
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003047 lys_node_free(retval, NULL);
Radek Krejci863c2852015-06-03 15:47:11 +02003048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003050}
3051
Michal Vasko0d343d12015-08-24 14:57:36 +02003052/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003053static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003054read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003055 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003056{
Radek Krejci76512572015-08-04 09:47:08 +02003057 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003058 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 struct lyxml_elem *sub, *next;
3060 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003061 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003062 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003065 if (!leaf) {
3066 LOGMEM;
3067 return NULL;
3068 }
Radek Krejci76512572015-08-04 09:47:08 +02003069 leaf->nodetype = LYS_LEAF;
3070 leaf->prev = (struct lys_node *)leaf;
3071 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072
Michal Vaskoe0c59842015-09-24 13:52:20 +02003073 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3074 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 goto error;
3076 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003077
Radek Krejcia9544502015-08-14 08:24:29 +02003078 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003079
Radek Krejcic071c542016-01-27 14:57:51 +01003080 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003081 goto error;
3082 }
3083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003085 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3086 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003087 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003088 continue;
3089 }
3090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003092 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003093 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 goto error;
3095 }
Michal Vasko88c29542015-11-27 14:57:53 +01003096 /* HACK for unres */
3097 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003098 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003099 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3100 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 goto error;
3102 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003103 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 } else if (!strcmp(sub->name, "default")) {
3105 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003106 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 goto error;
3108 }
3109 GETVAL(value, sub, "value");
3110 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003111 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003112 } else if (!strcmp(sub->name, "units")) {
3113 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003114 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 goto error;
3116 }
3117 GETVAL(value, sub, "name");
3118 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3119 } else if (!strcmp(sub->name, "mandatory")) {
3120 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003121 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 goto error;
3123 }
3124 /* just checking the flags in leaf is not sufficient, we would allow
3125 * multiple mandatory statements with the "false" value
3126 */
3127 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 GETVAL(value, sub, "value");
3130 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003131 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003132 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003133 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003134 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003135 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 goto error;
3137 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003138 } else if (!strcmp(sub->name, "when")) {
3139 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003140 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003141 goto error;
3142 }
3143
3144 leaf->when = read_yin_when(module, sub);
3145 if (!leaf->when) {
3146 goto error;
3147 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003148 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003149 goto error;
3150 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003152 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003153 c_must++;
3154 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003155 } else if (!strcmp(sub->name, "if-feature")) {
3156 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003157 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003160 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003161 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003163
Michal Vasko88c29542015-11-27 14:57:53 +01003164 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003168 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003169 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 goto error;
3171 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003172 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003173 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003174 goto error;
3175 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 /* middle part - process nodes with cardinality of 0..n */
3179 if (c_must) {
3180 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003181 if (!leaf->must) {
3182 LOGMEM;
3183 goto error;
3184 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003186 if (c_ftrs) {
3187 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003188 if (!leaf->features) {
3189 LOGMEM;
3190 goto error;
3191 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003192 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003193
Radek Krejci73adb602015-07-02 18:07:40 +02003194 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003196 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3197 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 if (r) {
3199 goto error;
3200 }
Michal Vasko0d204592015-10-07 09:50:04 +02003201 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003202 goto error;
3203 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003204 } else if (!strcmp(sub->name, "if-feature")) {
3205 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003206 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003207 goto error;
3208 }
Radek Krejcicf509982015-12-15 09:22:44 +01003209 /* hack - store pointer to the parent node for later status check */
3210 leaf->features[leaf->features_size] = (struct lys_feature *)leaf;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003211 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003212 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003213 leaf->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003214 lydict_remove(module->ctx, value);
3215 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003216 goto error;
3217 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003222
3223error:
3224
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003225 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003227 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003228}
3229
Michal Vasko0d343d12015-08-24 14:57:36 +02003230/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003231static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003232read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003233 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003234{
Radek Krejci76512572015-08-04 09:47:08 +02003235 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003236 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 struct lyxml_elem *sub, *next;
3238 const char *value;
3239 char *endptr;
3240 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003241 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003242 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003246 if (!llist) {
3247 LOGMEM;
3248 return NULL;
3249 }
Radek Krejci76512572015-08-04 09:47:08 +02003250 llist->nodetype = LYS_LEAFLIST;
3251 llist->prev = (struct lys_node *)llist;
3252 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003253
Michal Vaskoe0c59842015-09-24 13:52:20 +02003254 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3255 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 goto error;
3257 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003258
Radek Krejcia9544502015-08-14 08:24:29 +02003259 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003260
Radek Krejcic071c542016-01-27 14:57:51 +01003261 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003262 goto error;
3263 }
3264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003266 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3267 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003268 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003269 continue;
3270 }
3271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003273 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003274 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 goto error;
3276 }
Michal Vasko88c29542015-11-27 14:57:53 +01003277 /* HACK for unres */
3278 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003279 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003280 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3281 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003282 goto error;
3283 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003284 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 } else if (!strcmp(sub->name, "units")) {
3286 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003287 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 goto error;
3289 }
3290 GETVAL(value, sub, "name");
3291 llist->units = lydict_insert(module->ctx, value, strlen(value));
3292 } else if (!strcmp(sub->name, "ordered-by")) {
3293 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003294 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003295 goto error;
3296 }
3297 /* just checking the flags in llist is not sufficient, we would
3298 * allow multiple ordered-by statements with the "system" value
3299 */
3300 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003301
Radek Krejci1574a8d2015-08-03 14:16:52 +02003302 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3304 * state data
3305 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003306 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 continue;
3308 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 GETVAL(value, sub, "value");
3311 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003312 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003314 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003315 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003316 } /* else system is the default value, so we can ignore it */
3317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 } else if (!strcmp(sub->name, "must")) {
3319 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003320 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003321 } else if (!strcmp(sub->name, "if-feature")) {
3322 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 } else if (!strcmp(sub->name, "min-elements")) {
3326 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003327 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 goto error;
3329 }
3330 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 GETVAL(value, sub, "value");
3333 while (isspace(value[0])) {
3334 value++;
3335 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 /* convert it to uint32_t */
3338 errno = 0;
3339 endptr = NULL;
3340 val = strtoul(value, &endptr, 10);
3341 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003342 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
3344 }
3345 llist->min = (uint32_t) val;
3346 } else if (!strcmp(sub->name, "max-elements")) {
3347 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003348 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 goto error;
3350 }
3351 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 GETVAL(value, sub, "value");
3354 while (isspace(value[0])) {
3355 value++;
3356 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 /* convert it to uint32_t */
3359 errno = 0;
3360 endptr = NULL;
3361 val = strtoul(value, &endptr, 10);
3362 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003363 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 goto error;
3365 }
3366 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003367 } else if (!strcmp(sub->name, "when")) {
3368 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003369 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003370 goto error;
3371 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003372
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003373 llist->when = read_yin_when(module, sub);
3374 if (!llist->when) {
3375 goto error;
3376 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003377 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003378 goto error;
3379 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003381 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003384
Michal Vasko88c29542015-11-27 14:57:53 +01003385 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003389 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003390 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 goto error;
3392 }
3393 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003394 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 goto error;
3396 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 /* middle part - process nodes with cardinality of 0..n */
3399 if (c_must) {
3400 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003401 if (!llist->must) {
3402 LOGMEM;
3403 goto error;
3404 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003406 if (c_ftrs) {
3407 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003408 if (!llist->features) {
3409 LOGMEM;
3410 goto error;
3411 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003412 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003413
Radek Krejci73adb602015-07-02 18:07:40 +02003414 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003416 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3417 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 if (r) {
3419 goto error;
3420 }
Michal Vasko0d204592015-10-07 09:50:04 +02003421 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003422 goto error;
3423 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003424 } else if (!strcmp(sub->name, "if-feature")) {
3425 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003426 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003427 goto error;
3428 }
Radek Krejcicf509982015-12-15 09:22:44 +01003429 /* hack - store pointer to the parent node for later status check */
3430 llist->features[llist->features_size] = (struct lys_feature *)llist;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003431 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003432 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003433 llist->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003434 lydict_remove(module->ctx, value);
3435 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003436 goto error;
3437 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003438 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003442
3443error:
3444
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003445 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003448}
3449
Michal Vasko0d343d12015-08-24 14:57:36 +02003450/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003451static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003452read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3453 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003454{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003455 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003456 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003458 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003459 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003461 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 char *auxs;
3463 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 /* init */
3466 memset(&root, 0, sizeof root);
3467 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003470 if (!list) {
3471 LOGMEM;
3472 return NULL;
3473 }
Radek Krejci76512572015-08-04 09:47:08 +02003474 list->nodetype = LYS_LIST;
3475 list->prev = (struct lys_node *)list;
3476 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003477
Michal Vaskoe0c59842015-09-24 13:52:20 +02003478 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3479 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 goto error;
3481 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003482
Radek Krejcia9544502015-08-14 08:24:29 +02003483 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 /* process list's specific children */
3486 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003487 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3488 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003489 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003490 continue;
3491 }
3492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 /* data statements */
3494 if (!strcmp(sub->name, "container") ||
3495 !strcmp(sub->name, "leaf-list") ||
3496 !strcmp(sub->name, "leaf") ||
3497 !strcmp(sub->name, "list") ||
3498 !strcmp(sub->name, "choice") ||
3499 !strcmp(sub->name, "uses") ||
3500 !strcmp(sub->name, "grouping") ||
3501 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003502 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003503 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 /* array counters */
3506 } else if (!strcmp(sub->name, "key")) {
3507 /* check cardinality 0..1 */
3508 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003509 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 goto error;
3511 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 /* count the number of keys */
3514 GETVAL(value, sub, "value");
3515 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003516 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 while ((value = strpbrk(value, " \t\n"))) {
3518 list->keys_size++;
3519 while (isspace(*value)) {
3520 value++;
3521 }
3522 }
3523 list->keys_size++;
3524 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003525 if (!list->keys) {
3526 LOGMEM;
3527 goto error;
3528 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 } else if (!strcmp(sub->name, "unique")) {
3530 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003531 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003532 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 } else if (!strcmp(sub->name, "typedef")) {
3534 c_tpdf++;
3535 } else if (!strcmp(sub->name, "must")) {
3536 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003537 } else if (!strcmp(sub->name, "if-feature")) {
3538 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 /* optional stetments */
3541 } else if (!strcmp(sub->name, "ordered-by")) {
3542 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003543 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 goto error;
3545 }
3546 /* just checking the flags in llist is not sufficient, we would
3547 * allow multiple ordered-by statements with the "system" value
3548 */
3549 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003550
Radek Krejci1574a8d2015-08-03 14:16:52 +02003551 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3553 * state data
3554 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003555 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003556 continue;
3557 }
Radek Krejci345ad742015-06-03 11:04:18 +02003558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 GETVAL(value, sub, "value");
3560 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003561 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003563 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 goto error;
3565 }
3566 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003567 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 } else if (!strcmp(sub->name, "min-elements")) {
3569 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003570 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 goto error;
3572 }
3573 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 GETVAL(value, sub, "value");
3576 while (isspace(value[0])) {
3577 value++;
3578 }
Radek Krejci345ad742015-06-03 11:04:18 +02003579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 /* convert it to uint32_t */
3581 errno = 0;
3582 auxs = NULL;
3583 val = strtoul(value, &auxs, 10);
3584 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003585 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 goto error;
3587 }
3588 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003589 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 } else if (!strcmp(sub->name, "max-elements")) {
3591 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003592 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 goto error;
3594 }
3595 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 GETVAL(value, sub, "value");
3598 while (isspace(value[0])) {
3599 value++;
3600 }
Radek Krejci345ad742015-06-03 11:04:18 +02003601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 /* convert it to uint32_t */
3603 errno = 0;
3604 auxs = NULL;
3605 val = strtoul(value, &auxs, 10);
3606 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003607 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 goto error;
3609 }
3610 list->max = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003611 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003612 } else if (!strcmp(sub->name, "when")) {
3613 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003614 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003615 goto error;
3616 }
3617
3618 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003619 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003620 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003621 goto error;
3622 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003623 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003624 goto error;
3625 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003626 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003627 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003628 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003629 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003630 }
3631 }
Radek Krejci345ad742015-06-03 11:04:18 +02003632
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003634 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003635 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 goto error;
3637 }
3638 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003639 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640 goto error;
3641 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3644 if (c_tpdf) {
3645 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003646 if (!list->tpdf) {
3647 LOGMEM;
3648 goto error;
3649 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003651 if (c_must) {
3652 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003653 if (!list->must) {
3654 LOGMEM;
3655 goto error;
3656 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003657 }
3658 if (c_ftrs) {
3659 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003660 if (!list->features) {
3661 LOGMEM;
3662 goto error;
3663 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003664 }
Radek Krejci73adb602015-07-02 18:07:40 +02003665 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003667 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3668 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 if (r) {
3670 goto error;
3671 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003672 } else if (!strcmp(sub->name, "if-feature")) {
3673 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003674 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003675 goto error;
3676 }
Radek Krejcicf509982015-12-15 09:22:44 +01003677 /* hack - store pointer to the parent node for later status check */
3678 list->features[list->features_size] = (struct lys_feature *)list;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003679 r = unres_schema_add_str(module, unres, &list->features[list->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003680 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003681 list->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003682 lydict_remove(module->ctx, value);
3683 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003684 goto error;
3685 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003686 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003687 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3688 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 if (r) {
3690 goto error;
3691 }
Michal Vasko0d204592015-10-07 09:50:04 +02003692 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003693 goto error;
3694 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 }
3696 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003697
Radek Krejcic071c542016-01-27 14:57:51 +01003698 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003699 goto error;
3700 }
3701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 /* last part - process data nodes */
3703 LY_TREE_FOR_SAFE(root.child, next, sub) {
3704 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003705 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003707 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003709 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003711 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003713 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003715 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003717 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003719 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003720 } else {
3721 LOGINT;
3722 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003723 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003724 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 goto error;
3726 }
Radek Krejci73adb602015-07-02 18:07:40 +02003727
Michal Vasko345da0a2015-12-02 10:35:55 +01003728 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 if (!key_str) {
3732 /* config false list without a key */
3733 return retval;
3734 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003735 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003736 goto error;
3737 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 /* process unique statements */
3740 if (c_uniq) {
3741 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003742 if (!list->unique) {
3743 LOGMEM;
3744 goto error;
3745 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 }
3747 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003748 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3749 list->unique_size++;
3750 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003751 goto error;
3752 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003753
Michal Vasko345da0a2015-12-02 10:35:55 +01003754 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003758
3759error:
3760
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003761 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003763 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003764 }
3765 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003766 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003770}
3771
Michal Vasko0d343d12015-08-24 14:57:36 +02003772/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003773static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003774read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3775 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003778 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003779 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003780 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003781 const char *value;
3782 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003783 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003785 /* init */
3786 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003788 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003789 if (!cont) {
3790 LOGMEM;
3791 return NULL;
3792 }
Radek Krejci76512572015-08-04 09:47:08 +02003793 cont->nodetype = LYS_CONTAINER;
3794 cont->prev = (struct lys_node *)cont;
3795 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003796
Michal Vaskoe0c59842015-09-24 13:52:20 +02003797 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3798 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 goto error;
3800 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003801
Radek Krejcia9544502015-08-14 08:24:29 +02003802 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 /* process container's specific children */
3805 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003806 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003807 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003808 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003809 continue;
3810 }
3811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 if (!strcmp(sub->name, "presence")) {
3813 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003814 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 goto error;
3816 }
3817 GETVAL(value, sub, "value");
3818 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003819
Michal Vasko345da0a2015-12-02 10:35:55 +01003820 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003821 } else if (!strcmp(sub->name, "when")) {
3822 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003823 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003824 goto error;
3825 }
3826
3827 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003828 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003829 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003830 goto error;
3831 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003832 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003833 goto error;
3834 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003835 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 /* data statements */
3838 } else if (!strcmp(sub->name, "container") ||
3839 !strcmp(sub->name, "leaf-list") ||
3840 !strcmp(sub->name, "leaf") ||
3841 !strcmp(sub->name, "list") ||
3842 !strcmp(sub->name, "choice") ||
3843 !strcmp(sub->name, "uses") ||
3844 !strcmp(sub->name, "grouping") ||
3845 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003846 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003847 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 /* array counters */
3850 } else if (!strcmp(sub->name, "typedef")) {
3851 c_tpdf++;
3852 } else if (!strcmp(sub->name, "must")) {
3853 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003854 } else if (!strcmp(sub->name, "if-feature")) {
3855 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003856 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003857 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 }
3860 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3863 if (c_tpdf) {
3864 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003865 if (!cont->tpdf) {
3866 LOGMEM;
3867 goto error;
3868 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 }
3870 if (c_must) {
3871 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003872 if (!cont->must) {
3873 LOGMEM;
3874 goto error;
3875 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003877 if (c_ftrs) {
3878 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003879 if (!cont->features) {
3880 LOGMEM;
3881 goto error;
3882 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003883 }
Radek Krejci800af702015-06-02 13:46:01 +02003884
Radek Krejci73adb602015-07-02 18:07:40 +02003885 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003887 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3888 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 if (r) {
3890 goto error;
3891 }
3892 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003893 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3894 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003895 if (r) {
3896 goto error;
3897 }
Michal Vasko0d204592015-10-07 09:50:04 +02003898 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003899 goto error;
3900 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003901 } else if (!strcmp(sub->name, "if-feature")) {
3902 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003903 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003904 goto error;
3905 }
Radek Krejcicf509982015-12-15 09:22:44 +01003906 /* hack - store pointer to the parent node for later status check */
3907 cont->features[cont->features_size] = (struct lys_feature *)cont;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003908 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003909 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003910 cont->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003911 lydict_remove(module->ctx, value);
3912 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003913 goto error;
3914 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003916 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003917
Radek Krejcic071c542016-01-27 14:57:51 +01003918 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003919 goto error;
3920 }
3921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 /* last part - process data nodes */
3923 LY_TREE_FOR_SAFE(root.child, next, sub) {
3924 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003925 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003927 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003929 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003931 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003933 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003935 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003937 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003939 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003940 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 goto error;
3943 }
Radek Krejci73adb602015-07-02 18:07:40 +02003944
Michal Vasko345da0a2015-12-02 10:35:55 +01003945 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003949
3950error:
3951
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003952 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003954 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003958}
3959
Michal Vasko0d343d12015-08-24 14:57:36 +02003960/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003961static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003963 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003964{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003966 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003967 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003968 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 int r;
3970 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003972 /* init */
3973 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003976 if (!grp) {
3977 LOGMEM;
3978 return NULL;
3979 }
Radek Krejci76512572015-08-04 09:47:08 +02003980 grp->nodetype = LYS_GROUPING;
3981 grp->prev = (struct lys_node *)grp;
3982 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003983
Michal Vasko71e1aa82015-08-12 12:17:51 +02003984 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 goto error;
3986 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003987
Radek Krejcia9544502015-08-14 08:24:29 +02003988 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3989
Radek Krejci1d82ef62015-08-07 14:44:40 +02003990 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003991 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3992 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003993 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003994 continue;
3995 }
3996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003997 /* data statements */
3998 if (!strcmp(sub->name, "container") ||
3999 !strcmp(sub->name, "leaf-list") ||
4000 !strcmp(sub->name, "leaf") ||
4001 !strcmp(sub->name, "list") ||
4002 !strcmp(sub->name, "choice") ||
4003 !strcmp(sub->name, "uses") ||
4004 !strcmp(sub->name, "grouping") ||
4005 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004006 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004007 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 /* array counters */
4010 } else if (!strcmp(sub->name, "typedef")) {
4011 c_tpdf++;
4012 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004013 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004014 goto error;
4015 }
4016 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004018 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4019 if (c_tpdf) {
4020 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004021 if (!grp->tpdf) {
4022 LOGMEM;
4023 goto error;
4024 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004025 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004026 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004027 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4028 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004029 if (r) {
4030 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004031 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004032 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004033
Radek Krejcic071c542016-01-27 14:57:51 +01004034 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004035 goto error;
4036 }
4037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004038 /* last part - process data nodes */
4039 LY_TREE_FOR_SAFE(root.child, next, sub) {
4040 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004041 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004042 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004043 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004044 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004045 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004046 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004047 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004048 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004049 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004051 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004052 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004053 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004055 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004056 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004057 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 goto error;
4059 }
Radek Krejci73adb602015-07-02 18:07:40 +02004060
Michal Vasko345da0a2015-12-02 10:35:55 +01004061 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004065
4066error:
4067
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004068 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004069 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004070 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004071 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004073 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004074}
4075
Michal Vasko0d343d12015-08-24 14:57:36 +02004076/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004077static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004078read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4079 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004080{
Radek Krejcie0674f82015-06-15 13:58:51 +02004081 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004083 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004084 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004085 int r;
4086 int c_tpdf = 0;
4087
Radek Krejcie0674f82015-06-15 13:58:51 +02004088 /* init */
4089 memset(&root, 0, sizeof root);
4090
Michal Vasko38d01f72015-06-15 09:41:06 +02004091 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004092 if (!inout) {
4093 LOGMEM;
4094 return NULL;
4095 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004096 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004097
4098 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004099 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004100 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004101 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004102 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004103 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004104 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004105 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004106 }
4107
Radek Krejci76512572015-08-04 09:47:08 +02004108 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004109
Radek Krejci6a113852015-07-03 16:04:20 +02004110 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004111 goto error;
4112 }
4113
Radek Krejcia9544502015-08-14 08:24:29 +02004114 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4115
Michal Vasko38d01f72015-06-15 09:41:06 +02004116 /* data statements */
4117 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004118 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4119 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004120 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004121 continue;
4122 }
4123
Michal Vasko38d01f72015-06-15 09:41:06 +02004124 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004125 !strcmp(sub->name, "leaf-list") ||
4126 !strcmp(sub->name, "leaf") ||
4127 !strcmp(sub->name, "list") ||
4128 !strcmp(sub->name, "choice") ||
4129 !strcmp(sub->name, "uses") ||
4130 !strcmp(sub->name, "grouping") ||
4131 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004132 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004133 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004136 } else if (!strcmp(sub->name, "typedef")) {
4137 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004138
Michal Vasko38d01f72015-06-15 09:41:06 +02004139 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004140 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004141 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004142 }
4143 }
4144
4145 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4146 if (c_tpdf) {
4147 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004148 if (!inout->tpdf) {
4149 LOGMEM;
4150 goto error;
4151 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004152 }
4153
Radek Krejci73adb602015-07-02 18:07:40 +02004154 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004155 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4156 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004157 if (r) {
4158 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004159 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004160 }
4161
Radek Krejcic071c542016-01-27 14:57:51 +01004162 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004163 goto error;
4164 }
4165
Michal Vasko38d01f72015-06-15 09:41:06 +02004166 /* last part - process data nodes */
4167 LY_TREE_FOR_SAFE(root.child, next, sub) {
4168 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004169 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004171 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004172 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004173 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004174 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004175 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004176 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004177 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004178 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004179 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004180 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004181 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004182 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004183 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004184 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004185 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004186 goto error;
4187 }
Radek Krejci73adb602015-07-02 18:07:40 +02004188
Michal Vasko345da0a2015-12-02 10:35:55 +01004189 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004190 }
4191
Michal Vasko38d01f72015-06-15 09:41:06 +02004192 return retval;
4193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004194error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004195
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004196 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004197 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004198 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004199 }
4200
4201 return NULL;
4202}
4203
Michal Vasko0d343d12015-08-24 14:57:36 +02004204/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004205static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004206read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4207 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004208{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004209 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004210 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004211 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004212 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004213 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004214 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004215 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004216
Michal Vaskoc6551b32015-06-16 10:51:43 +02004217 memset(&root, 0, sizeof root);
4218
Michal Vasko0ea41032015-06-16 08:53:55 +02004219 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004220 if (!notif) {
4221 LOGMEM;
4222 return NULL;
4223 }
Radek Krejci76512572015-08-04 09:47:08 +02004224 notif->nodetype = LYS_NOTIF;
4225 notif->prev = (struct lys_node *)notif;
4226 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004227
Radek Krejci6a113852015-07-03 16:04:20 +02004228 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004229 goto error;
4230 }
4231
Radek Krejcia9544502015-08-14 08:24:29 +02004232 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4233
Michal Vasko0ea41032015-06-16 08:53:55 +02004234 /* process rpc's specific children */
4235 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004236 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4237 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004238 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004239 continue;
4240 }
4241
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 /* data statements */
4243 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004244 !strcmp(sub->name, "leaf-list") ||
4245 !strcmp(sub->name, "leaf") ||
4246 !strcmp(sub->name, "list") ||
4247 !strcmp(sub->name, "choice") ||
4248 !strcmp(sub->name, "uses") ||
4249 !strcmp(sub->name, "grouping") ||
4250 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004251 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004252 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004255 } else if (!strcmp(sub->name, "typedef")) {
4256 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004257 } else if (!strcmp(sub->name, "if-feature")) {
4258 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004259 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004260 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004261 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004262 }
4263 }
4264
4265 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4266 if (c_tpdf) {
4267 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004268 if (!notif->tpdf) {
4269 LOGMEM;
4270 goto error;
4271 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004272 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004273 if (c_ftrs) {
4274 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004275 if (!notif->features) {
4276 LOGMEM;
4277 goto error;
4278 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004279 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004280
Radek Krejci73adb602015-07-02 18:07:40 +02004281 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004282 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004283 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4284 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004285 if (r) {
4286 goto error;
4287 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004288 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004289 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004290 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004291 goto error;
4292 }
Radek Krejcicf509982015-12-15 09:22:44 +01004293 /* hack - store pointer to the parent node for later status check */
4294 notif->features[notif->features_size] = (struct lys_feature *)notif;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004295 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004296 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004297 notif->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004298 lydict_remove(module->ctx, value);
4299 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004300 goto error;
4301 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004302 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004303 }
4304
Radek Krejcic071c542016-01-27 14:57:51 +01004305 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004306 goto error;
4307 }
4308
Michal Vasko0ea41032015-06-16 08:53:55 +02004309 /* last part - process data nodes */
4310 LY_TREE_FOR_SAFE(root.child, next, sub) {
4311 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004312 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004313 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004314 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004315 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004316 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004317 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004318 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004319 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004320 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004321 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004322 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004323 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004324 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004325 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004326 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004327 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004328 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004329 goto error;
4330 }
Radek Krejci73adb602015-07-02 18:07:40 +02004331
Michal Vasko345da0a2015-12-02 10:35:55 +01004332 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004333 }
4334
Michal Vasko0ea41032015-06-16 08:53:55 +02004335 return retval;
4336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004338
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004339 lys_node_free(retval, NULL);
Michal Vasko0ea41032015-06-16 08:53:55 +02004340 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004341 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004342 }
4343
4344 return NULL;
4345}
4346
Michal Vasko0d343d12015-08-24 14:57:36 +02004347/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004348static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004349read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4350 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004351{
Radek Krejcie0674f82015-06-15 13:58:51 +02004352 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004353 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004354 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004355 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004356 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004357 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004358 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004359
Radek Krejcie0674f82015-06-15 13:58:51 +02004360 /* init */
4361 memset(&root, 0, sizeof root);
4362
Michal Vasko38d01f72015-06-15 09:41:06 +02004363 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004364 if (!rpc) {
4365 LOGMEM;
4366 return NULL;
4367 }
Radek Krejci76512572015-08-04 09:47:08 +02004368 rpc->nodetype = LYS_RPC;
4369 rpc->prev = (struct lys_node *)rpc;
4370 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004371
Radek Krejci6a113852015-07-03 16:04:20 +02004372 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004373 goto error;
4374 }
4375
Radek Krejcia9544502015-08-14 08:24:29 +02004376 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4377
Michal Vasko38d01f72015-06-15 09:41:06 +02004378 /* process rpc's specific children */
4379 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004380 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4381 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004382 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004383 continue;
4384 }
4385
Michal Vasko38d01f72015-06-15 09:41:06 +02004386 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004387 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004388 && (rpc->child->nodetype == LYS_INPUT
4389 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004390 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004391 goto error;
4392 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004393 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004394 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004395 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004397 && (rpc->child->nodetype == LYS_INPUT
4398 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004399 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004400 goto error;
4401 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004402 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004403 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004406 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004407 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004408 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004411 } else if (!strcmp(sub->name, "typedef")) {
4412 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004413 } else if (!strcmp(sub->name, "if-feature")) {
4414 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004415 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004416 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004417 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004418 }
4419 }
4420
4421 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4422 if (c_tpdf) {
4423 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004424 if (!rpc->tpdf) {
4425 LOGMEM;
4426 goto error;
4427 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004428 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004429 if (c_ftrs) {
4430 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004431 if (!rpc->features) {
4432 LOGMEM;
4433 goto error;
4434 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004435 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004436
Radek Krejci73adb602015-07-02 18:07:40 +02004437 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004438 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004439 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4440 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004441 if (r) {
4442 goto error;
4443 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004444 } else if (!strcmp(sub->name, "if-feature")) {
4445 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004446 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004447 goto error;
4448 }
Radek Krejcicf509982015-12-15 09:22:44 +01004449 /* hack - store pointer to the parent node for later status check */
4450 rpc->features[rpc->features_size] = (struct lys_feature *)rpc;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004451 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004452 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004453 rpc->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004454 lydict_remove(module->ctx, value);
4455 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004456 goto error;
4457 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004458 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004459 }
4460
Radek Krejcic071c542016-01-27 14:57:51 +01004461 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004462 goto error;
4463 }
4464
Michal Vasko38d01f72015-06-15 09:41:06 +02004465 /* last part - process data nodes */
4466 LY_TREE_FOR_SAFE(root.child, next, sub) {
4467 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004468 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004469 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004470 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004471 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004472 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004473 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004474 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004475 goto error;
4476 }
Radek Krejci73adb602015-07-02 18:07:40 +02004477
Michal Vasko345da0a2015-12-02 10:35:55 +01004478 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004479 }
4480
Michal Vasko38d01f72015-06-15 09:41:06 +02004481 return retval;
4482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004483error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004484
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004485 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004486 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004487 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004488 }
4489
4490 return NULL;
4491}
4492
Michal Vasko0d343d12015-08-24 14:57:36 +02004493/* logs directly
4494 *
Radek Krejci74705112015-06-05 10:25:44 +02004495 * resolve - referenced grouping should be bounded to the namespace (resolved)
4496 * only when uses does not appear in grouping. In a case of grouping's uses,
4497 * we just get information but we do not apply augment or refine to it.
4498 */
Radek Krejci76512572015-08-04 09:47:08 +02004499static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004500read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004501 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004502{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004504 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004505 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004507 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004508 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004511 if (!uses) {
4512 LOGMEM;
4513 return NULL;
4514 }
Radek Krejci76512572015-08-04 09:47:08 +02004515 uses->nodetype = LYS_USES;
4516 uses->prev = (struct lys_node *)uses;
4517 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004518
Radek Krejcia9544502015-08-14 08:24:29 +02004519 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004521
Michal Vaskoe0c59842015-09-24 13:52:20 +02004522 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4523 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 goto error;
4525 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004526
Radek Krejcia9544502015-08-14 08:24:29 +02004527 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004529 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004530 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004531 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4532 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004533 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004534 continue;
4535 }
4536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 if (!strcmp(sub->name, "refine")) {
4538 c_ref++;
4539 } else if (!strcmp(sub->name, "augment")) {
4540 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004541 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004542 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004543 } else if (!strcmp(sub->name, "when")) {
4544 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004545 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004546 goto error;
4547 }
4548
4549 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004550 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004551 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004552 goto error;
4553 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004554 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004555 goto error;
4556 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004557 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004559 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 }
4562 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 /* process properties with cardinality 0..n */
4565 if (c_ref) {
4566 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004567 if (!uses->refine) {
4568 LOGMEM;
4569 goto error;
4570 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 }
4572 if (c_aug) {
4573 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004574 if (!uses->augment) {
4575 LOGMEM;
4576 goto error;
4577 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004579 if (c_ftrs) {
4580 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004581 if (!uses->features) {
4582 LOGMEM;
4583 goto error;
4584 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004585 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004586
Radek Krejcic071c542016-01-27 14:57:51 +01004587 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004588 goto error;
4589 }
4590
Radek Krejcia9544502015-08-14 08:24:29 +02004591 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004593 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4594 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004595 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004596 goto error;
4597 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004598 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004599 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4600 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004601 if (r) {
4602 goto error;
4603 }
4604 } else if (!strcmp(sub->name, "if-feature")) {
4605 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004606 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004607 goto error;
4608 }
Radek Krejcicf509982015-12-15 09:22:44 +01004609 /* hack - store pointer to the parent node for later status check */
4610 uses->features[uses->features_size] = (struct lys_feature *)uses;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004611 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02004612 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004613 uses->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004614 lydict_remove(module->ctx, value);
4615 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004616 goto error;
4617 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 }
4619 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004620
Michal Vasko0bd29d12015-08-19 11:45:49 +02004621 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004622 goto error;
4623 }
Radek Krejci74705112015-06-05 10:25:44 +02004624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 if (resolve) {
4626 /* inherit config flag */
4627 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004628 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 } else {
4630 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004631 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 }
4633 }
Radek Krejcib388c152015-06-04 17:03:03 +02004634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004636
4637error:
4638
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004639 lys_node_free(retval, NULL);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004642}
4643
Michal Vasko0d343d12015-08-24 14:57:36 +02004644/* logs directly
4645 *
4646 * common code for yin_read_module() and yin_read_submodule()
4647 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648static int
Radek Krejcic071c542016-01-27 14:57:51 +01004649read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4650 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004651{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004653 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004654 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004655 struct lys_module *trg;
4656 struct lys_import *aux_imp;
4657 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004659 int i, j, r;
4660 int inc_size_aux = 0;
4661 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004662 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004663 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 +02004664
Radek Krejcic071c542016-01-27 14:57:51 +01004665 /* to simplify code, store the module/submodule being processed as trg */
4666 trg = submodule ? (struct lys_module*)submodule : module;
4667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 /* init */
4669 memset(&root, 0, sizeof root);
4670 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004671 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 /*
4674 * in the first run, we process elements with cardinality of 1 or 0..1 and
4675 * count elements with cardinality 0..n. Data elements (choices, containers,
4676 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4677 * need have all top-level and groupings already prepared at that time. In
4678 * the middle loop, we process other elements with carinality of 0..n since
4679 * we need to allocate arrays to store them.
4680 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004681 LY_TREE_FOR_SAFE(yin->child, next, child) {
4682 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004683 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004684 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 continue;
4686 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004687
Radek Krejcic071c542016-01-27 14:57:51 +01004688 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 goto error;
4692 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004693 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004695 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004696 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004698 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 goto error;
4700 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004702 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004703 goto error;
4704 }
4705 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004706 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004707 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4708 if (submodule->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004709 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 goto error;
4711 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004714 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004715 goto error;
4716 }
Radek Krejcif3886932015-06-04 17:36:06 +02004717
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004719 if (!child->child) {
4720 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004722 } else if (strcmp(child->child->name, "prefix")) {
4723 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004725 } else if (child->child->next) {
4726 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
4729 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004730 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 /* check here differs from a generic prefix check, since this prefix
4732 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004733 */
Radek Krejcic6556022016-01-27 15:16:45 +01004734 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 goto error;
4736 }
Radek Krejcic071c542016-01-27 14:57:51 +01004737 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004739 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004740 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004741
4742 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004743 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004745 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004747 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004749 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004751 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004753 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004754 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004755 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004756 lyxml_unlink_elem(ctx, child, 2);
4757 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004758
Radek Krejci1d82ef62015-08-07 14:44:40 +02004759 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004760 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004761 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004762 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004765 } else if (!strcmp(child->name, "container") ||
4766 !strcmp(child->name, "leaf-list") ||
4767 !strcmp(child->name, "leaf") ||
4768 !strcmp(child->name, "list") ||
4769 !strcmp(child->name, "choice") ||
4770 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004771 !strcmp(child->name, "anyxml") ||
4772 !strcmp(child->name, "rpc") ||
4773 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004774 lyxml_unlink_elem(ctx, child, 2);
4775 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004776
Radek Krejci1d82ef62015-08-07 14:44:40 +02004777 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004778 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004779 lyxml_unlink_elem(ctx, child, 2);
4780 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004783 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004784 if (trg->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004785 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004786 goto error;
4787 }
Radek Krejcic071c542016-01-27 14:57:51 +01004788 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004789 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004790 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 goto error;
4792 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004793 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004794 if (trg->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004795 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004796 goto error;
4797 }
Radek Krejcic071c542016-01-27 14:57:51 +01004798 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004799 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004800 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 goto error;
4802 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004803 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004804 if (trg->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004805 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 goto error;
4807 }
Radek Krejcic071c542016-01-27 14:57:51 +01004808 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004809 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004810 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 goto error;
4812 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004813 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004814 if (trg->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004815 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 goto error;
4817 }
Radek Krejcic071c542016-01-27 14:57:51 +01004818 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004819 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004820 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004821 goto error;
4822 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004823 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004825 if (version_flag) {
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 Krejci1d82ef62015-08-07 14:44:40 +02004829 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004831 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004832 goto error;
4833 }
Radek Krejcic071c542016-01-27 14:57:51 +01004834 version_flag = 1;
4835 if (!submodule) {
4836 module->version = 1;
4837 } /* 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 +01004838 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004839
Radek Krejci1d82ef62015-08-07 14:44:40 +02004840 } else if (!strcmp(child->name, "extension")) {
4841 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004842
Radek Krejci3d468122015-10-02 13:36:12 +02004843 /* we have the following supported (hardcoded) extensions: */
4844 /* ietf-netconf's get-filter-element-attributes */
4845 if (!strcmp(module->ns, LY_NSNC) &&
4846 !strcmp(value, "get-filter-element-attributes")) {
4847 LOGDBG("NETCONF filter extension found");
4848 /* NACM's default-deny-write and default-deny-all */
4849 } else if (!strcmp(module->ns, LY_NSNACM) &&
4850 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4851 LOGDBG("NACM extension found");
4852 /* other extensions are not supported, so inform about such an extension */
4853 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004854 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004855 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004856 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004858 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 }
4861 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004862
Radek Krejcic071c542016-01-27 14:57:51 +01004863 /* check for mandatory statements */
4864 if (submodule && !submodule->prefix) {
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004865 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "belongs-to", "submodule");
4866 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004867 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004869 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 goto error;
4871 }
4872 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004873 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 goto error;
4875 }
4876 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 /* allocate arrays for elements with cardinality of 0..n */
4879 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004880 trg->imp = calloc(c_imp, sizeof *trg->imp);
4881 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004882 LOGMEM;
4883 goto error;
4884 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004885 }
4886 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004887 trg->rev = calloc(c_rev, sizeof *trg->rev);
4888 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004889 LOGMEM;
4890 goto error;
4891 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004892 }
4893 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004894 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4895 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004896 LOGMEM;
4897 goto error;
4898 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004899 }
4900 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004901 trg->ident = calloc(c_ident, sizeof *trg->ident);
4902 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004903 LOGMEM;
4904 goto error;
4905 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 }
4907 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004908 trg->inc = calloc(c_inc, sizeof *trg->inc);
4909 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004910 LOGMEM;
4911 goto error;
4912 }
Radek Krejcic071c542016-01-27 14:57:51 +01004913 trg->inc_size = c_inc;
4914 /* trg->inc_size can be updated by the included submodules,
4915 * so we will use inc_size_aux here, trg->inc_size stores the
4916 * target size of the array
4917 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004918 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004919 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004920 trg->augment = calloc(c_aug, sizeof *trg->augment);
4921 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004922 LOGMEM;
4923 goto error;
4924 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004925 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004926 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004927 trg->features = calloc(c_ftrs, sizeof *trg->features);
4928 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004929 LOGMEM;
4930 goto error;
4931 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004932 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004933 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004934 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4935 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004936 LOGMEM;
4937 goto error;
4938 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004939 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004940
Michal Vasko2f7925f2015-10-21 15:06:56 +02004941 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4942 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004943 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004944 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4945 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946 if (r) {
4947 goto error;
4948 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004950 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004951 for (i = 0; i < trg->imp_size - 1; i++) {
4952 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
4953 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004954 goto error;
4955 }
4956 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004957
Radek Krejci1d82ef62015-08-07 14:44:40 +02004958 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004959 memset(&inc, 0, sizeof inc);
4960 /* 1) pass module, not trg, since we want to pass the main module
4961 * 2) we cannot pass directly the structure in the array since
4962 * submodule parser can realloc our array of includes */
4963 r = fill_yin_include(module, child, &inc, unres);
4964 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4965 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 if (r) {
4967 goto error;
4968 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004970 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004971 for (i = 0; i < inc_size_aux - 1; i++) {
4972 if (!strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
4973 LOGVAL(LYE_SPEC, LOGLINE(child), "Including submodule \"%s\" repeatedly.",
4974 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004975 goto error;
4976 }
4977 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004978
Radek Krejci1d82ef62015-08-07 14:44:40 +02004979 } else if (!strcmp(child->name, "revision")) {
4980 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004981 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 goto error;
4983 }
Radek Krejcic071c542016-01-27 14:57:51 +01004984 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004986 for (i = 0; i < trg->rev_size; i++) {
4987 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004988 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004989 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004990 }
4991 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004992
Radek Krejci1d82ef62015-08-07 14:44:40 +02004993 LY_TREE_FOR(child->child, child2) {
4994 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004995 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004996 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 goto error;
4998 }
Radek Krejcic071c542016-01-27 14:57:51 +01004999 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5000 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 goto error;
5002 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005003 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005004 if (trg->rev[trg->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005005 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 goto error;
5007 }
Radek Krejcic071c542016-01-27 14:57:51 +01005008 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5009 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 goto error;
5011 }
5012 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005013 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005014 goto error;
5015 }
5016 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005019 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005020 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005021 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005022 if (!value) {
5023 LOGMEM;
5024 goto error;
5025 }
Radek Krejcic071c542016-01-27 14:57:51 +01005026 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5027 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005029
Radek Krejcic071c542016-01-27 14:57:51 +01005030 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
5031 value = trg->rev[0].dsc;
5032 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5033 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005034 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005035
Radek Krejcic071c542016-01-27 14:57:51 +01005036 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
5037 value = trg->rev[0].ref;
5038 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5039 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005040 }
5041 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005042
Radek Krejcic071c542016-01-27 14:57:51 +01005043 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005044
Radek Krejci1d82ef62015-08-07 14:44:40 +02005045 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005046 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5047 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005048 if (r) {
5049 goto error;
5050 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005051
Radek Krejci1d82ef62015-08-07 14:44:40 +02005052 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005053 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5054 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 if (r) {
5056 goto error;
5057 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005058
Radek Krejci1d82ef62015-08-07 14:44:40 +02005059 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005060 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5061 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005062 if (r) {
5063 goto error;
5064 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005065
Radek Krejci1d82ef62015-08-07 14:44:40 +02005066 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005067 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5068 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005069 if (r) {
5070 goto error;
5071 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005073 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005074 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005075
Radek Krejcic071c542016-01-27 14:57:51 +01005076 if (submodule) {
5077 /* propagate imports into the main module */
5078 for (i = r = 0; i < submodule->imp_size; i++) {
5079 for (j = 0; j < module->imp_size; j++) {
5080 if (submodule->imp[i].module == module->imp[j].module &&
5081 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5082 /* check prefix match */
5083 if (submodule->imp[i].prefix != module->imp[j].prefix) {
5084 LOGVAL(LYE_INID, LOGLINE(yin), submodule->imp[i].prefix,
5085 "non-matching prefixes of imported module in main module and submodule");
5086 goto error;
5087 }
5088 break;
5089 }
5090 }
5091 if (j == module->imp_size) {
5092 /* new import */
5093 r++;
5094 }
5095 }
5096 if (r) {
5097 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5098 if (!aux_imp) {
5099 LOGMEM;
5100 goto error;
5101 }
5102 module->imp = aux_imp;
5103 for (i = r = 0; i < submodule->imp_size; i++) {
5104 for (j = 0; j < module->imp_size; j++) {
5105 if (submodule->imp[i].module == module->imp[j].module) {
5106 break;
5107 }
5108 }
5109 if (j == module->imp_size) {
5110 /* new import */
5111 /* check prefix uniqueness */
5112 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
5113 LOGVAL(LYE_DUPID, LOGLINE(yin), "prefix", submodule->imp[i].prefix);
5114 goto error;
5115 }
5116 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5117 module->imp[module->imp_size + r].external = 1;
5118 r++;
5119 }
5120 }
5121 module->imp_size += r;
5122 }
5123
5124 /* propagate imports into the main module */
5125 for (i = r = 0; i < submodule->inc_size; i++) {
5126 for (j = 0; j < module->inc_size; j++) {
5127 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5128 break;
5129 }
5130 }
5131 if (j == module->inc_size) {
5132 /* new include */
5133 r++;
5134 }
5135 }
5136
5137 if (r) {
5138 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5139 if (!aux_inc) {
5140 LOGMEM;
5141 goto error;
5142 }
5143 module->inc = aux_inc;
5144 for (i = r = 0; i < submodule->inc_size; i++) {
5145 for (j = 0; j < module->inc_size; j++) {
5146 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5147 break;
5148 }
5149 }
5150 if (j == module->inc_size) {
5151 /* new include */
5152 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5153 module->inc[module->inc_size + r].external = 1;
5154 r++;
5155 }
5156 }
5157 module->inc_size += r;
5158 }
5159 }
5160
Radek Krejcif5be10f2015-06-16 13:29:36 +02005161 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005162 * refer to them. Submodule's data nodes are stored in the
5163 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005164 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005165 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005166 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005167 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005168 goto error;
5169 }
Radek Krejci74705112015-06-05 10:25:44 +02005170
Michal Vasko345da0a2015-12-02 10:35:55 +01005171 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 }
Radek Krejci74705112015-06-05 10:25:44 +02005173
Radek Krejcif5be10f2015-06-16 13:29:36 +02005174 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005175 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005176
Radek Krejci1d82ef62015-08-07 14:44:40 +02005177 if (!strcmp(child->name, "container")) {
5178 node = read_yin_container(module, NULL, child, 1, unres);
5179 } else if (!strcmp(child->name, "leaf-list")) {
5180 node = read_yin_leaflist(module, NULL, child, 1, unres);
5181 } else if (!strcmp(child->name, "leaf")) {
5182 node = read_yin_leaf(module, NULL, child, 1, unres);
5183 } else if (!strcmp(child->name, "list")) {
5184 node = read_yin_list(module, NULL, child, 1, unres);
5185 } else if (!strcmp(child->name, "choice")) {
5186 node = read_yin_choice(module, NULL, child, 1, unres);
5187 } else if (!strcmp(child->name, "uses")) {
5188 node = read_yin_uses(module, NULL, child, 1, unres);
5189 } else if (!strcmp(child->name, "anyxml")) {
5190 node = read_yin_anyxml(module, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005191 } else if (!strcmp(child->name, "rpc")) {
5192 node = read_yin_rpc(module, NULL, child, 0, unres);
5193 } else if (!strcmp(child->name, "notification")) {
5194 node = read_yin_notif(module, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005195 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005196 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 goto error;
5198 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005199
Michal Vasko345da0a2015-12-02 10:35:55 +01005200 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005201 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005202
Michal Vasko2f7925f2015-10-21 15:06:56 +02005203 /* ... and finally augments (last, so we can augment our data, for instance) */
5204 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005205 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5206 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005207
Michal Vasko2f7925f2015-10-21 15:06:56 +02005208 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005209 goto error;
5210 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005211 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005212 }
5213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005214 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005215
5216error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 /* cleanup */
5218 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005219 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 }
5221 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005222 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005224 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005225 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005226 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005228 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005229}
5230
Michal Vasko0d343d12015-08-24 14:57:36 +02005231/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005232struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01005233yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005234{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005235 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005236 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005237 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005239 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005240
Radek Krejci722b0072016-02-01 17:09:45 +01005241 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005242 if (!yin) {
5243 return NULL;
5244 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005246 /* check root element */
5247 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005248 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 goto error;
5250 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005252 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005253 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 goto error;
5255 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 submodule = calloc(1, sizeof *submodule);
5258 if (!submodule) {
5259 LOGMEM;
5260 goto error;
5261 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 submodule->ctx = module->ctx;
5264 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5265 submodule->type = 1;
5266 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005267
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005268 LOGVRB("Reading submodule %s", submodule->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005269 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 goto error;
5271 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005274 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005275
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005276 LOGVRB("Submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005279
5280error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005282 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005283 lyxml_free(module->ctx, yin);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01005284 lys_submodule_free(submodule, 0, NULL);
Radek Krejciefaeba32015-05-27 14:30:57 +02005285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005287}
5288
Michal Vasko0d343d12015-08-24 14:57:36 +02005289/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005290struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005291yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005292{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005294 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005295 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 const char *value;
5297 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005298
Radek Krejcic071c542016-01-27 14:57:51 +01005299 unres = calloc(1, sizeof *unres);
5300 if (!unres) {
5301 LOGMEM;
5302 return NULL;
5303 }
5304
Radek Krejci722b0072016-02-01 17:09:45 +01005305 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005306 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005307 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005308 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005310 /* check root element */
5311 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005312 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 goto error;
5314 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005317 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 goto error;
5319 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005321 module = calloc(1, sizeof *module);
5322 if (!module) {
5323 LOGMEM;
5324 goto error;
5325 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005327 module->ctx = ctx;
5328 module->name = lydict_insert(ctx, value, strlen(value));
5329 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005330 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005331
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005332 LOGVRB("Reading module %s", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005333 if (read_sub_module(module, NULL, yin, unres)) {
5334 goto error;
5335 }
5336
5337 /* resolve rest of unres items */
5338 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005339 goto error;
5340 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 /* add to the context's list of modules */
5343 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005344 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005345 if (!newlist) {
5346 LOGMEM;
5347 goto error;
5348 }
5349 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5350 newlist[i] = NULL;
5351 }
5352 ctx->models.size *= 2;
5353 ctx->models.list = newlist;
5354 }
5355 for (i = 0; ctx->models.list[i]; i++) {
5356 /* check name (name/revision) and namespace uniqueness */
5357 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005358 if (ctx->models.list[i]->rev_size == module->rev_size) {
5359 /* both have the same number of revisions */
5360 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5361 /* both have the same revision -> we already have the same module */
5362 /* so free the new one and update the old one's implement flag if needed */
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005363 LOGVRB("Module %s already in context", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005364
Radek Krejcifa0b5e02016-02-04 13:57:03 +01005365 lys_free(module, 0, NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01005366 module = ctx->models.list[i];
5367 if (implement && !module->implemented) {
5368 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005369 }
Radek Krejcic071c542016-01-27 14:57:51 +01005370
5371 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005372 }
5373 }
Radek Krejcif647e612015-07-30 11:36:07 +02005374 /* else (both elses) keep searching, for now the caller is just adding
5375 * another revision of an already present schema
5376 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005377 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
5378 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
5379 ctx->models.list[i]->name, module->name, module->ns);
5380 goto error;
5381 }
5382 }
5383 ctx->models.list[i] = module;
5384 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005385 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005386
Radek Krejcic071c542016-01-27 14:57:51 +01005387success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005388 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005389 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005390 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005391
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005392 LOGVRB("Module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005394 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005395
5396error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005398 unres_schema_free(module, &unres);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01005399 lys_free(module, 0, NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01005400 lyxml_free(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005402 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005403}