blob: eebb2f3903eaf00491d0cdcb277742cdc9d15be1 [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 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Radek Krejcic6556022016-01-27 15:16:45 +010042/* parser.c */
43int dup_prefix_check(const char *prefix, struct lys_module *module);
44
Radek Krejcib388c152015-06-04 17:03:03 +020045#define OPT_IDENT 0x01
46#define OPT_CONFIG 0x02
47#define OPT_MODULE 0x04
48#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020049#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020050static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020051
Radek Krejcib8048692015-08-05 13:36:34 +020052static 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 +020053 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020054static 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 +020055 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static 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 +020057 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static 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 +020059 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static 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 +020061 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static 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 +020063 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020064static 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 +020065 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020066static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci3440cc52016-06-23 17:03:59 +020067 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020068static 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 +020069 int resolve, struct unres_schema *unres);
70static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020071
Michal Vasko0d343d12015-08-24 14:57:36 +020072/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020073static const char *
74read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020075{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020076 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020078 /* there should be <text> child */
79 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010080 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010081 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010082 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020083 } else if (node->child->content) {
84 len = strlen(node->child->content);
85 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010086 } else {
87 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020088 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020089}
90
Michal Vasko0d343d12015-08-24 14:57:36 +020091/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020092static int
Michal Vaskoc5c26b02016-06-29 11:10:29 +020093fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, const char **iffeat_expr, struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +010094{
95 int r;
96 const char *value;
97
98 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +010099 if (!(value = transform_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100100 return EXIT_FAILURE;
101 }
102
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200103 *iffeat_expr = value;
104
105 r = unres_schema_add_node(parent->module, unres, (char *)value, UNRES_IFFEAT, parent);
Michal Vasko1d337e12016-02-15 12:32:04 +0100106 if (!r) {
107 return EXIT_SUCCESS;
108 }
109
110error:
111 return EXIT_FAILURE;
112}
113
114/* logs directly */
115static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200116fill_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 +0200117{
Radek Krejci73adb602015-07-02 18:07:40 +0200118 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200119 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100120 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200121
Michal Vasko4cfcd252015-08-03 14:31:10 +0200122 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100123 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200124
Radek Krejci76512572015-08-04 09:47:08 +0200125 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200126 return EXIT_FAILURE;
127 }
Radek Krejci04581c62015-05-22 21:24:00 +0200128
Radek Krejci73adb602015-07-02 18:07:40 +0200129 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200130 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
131 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200132 continue;
133 }
134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200135 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100136 if (base_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100137 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200138 return EXIT_FAILURE;
139 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100140 base_flag = 1;
141
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200142 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100143 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100144 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200145 return EXIT_FAILURE;
146 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100147
Radek Krejci48464ed2016-03-17 15:44:09 +0100148 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100149 lydict_remove(module->ctx, value);
150 return EXIT_FAILURE;
151 }
152 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200153 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100154 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200155 return EXIT_FAILURE;
156 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200157 }
Radek Krejci04581c62015-05-22 21:24:00 +0200158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200159 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200160
161error:
162 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200163}
164
Michal Vasko0d343d12015-08-24 14:57:36 +0200165/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200166static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200167read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200168{
Radek Krejci73adb602015-07-02 18:07:40 +0200169 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200170 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200171
Radek Krejci73adb602015-07-02 18:07:40 +0200172 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200173 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
174 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200175 continue;
176 }
177
Radek Krejci41726f92015-06-19 13:11:05 +0200178 if (!strcmp(child->name, "description")) {
179 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100180 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200181 return EXIT_FAILURE;
182 }
183 restr->dsc = read_yin_subnode(ctx, child, "text");
184 if (!restr->dsc) {
185 return EXIT_FAILURE;
186 }
187 } else if (!strcmp(child->name, "reference")) {
188 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100189 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200190 return EXIT_FAILURE;
191 }
192 restr->ref = read_yin_subnode(ctx, child, "text");
193 if (!restr->ref) {
194 return EXIT_FAILURE;
195 }
196 } else if (!strcmp(child->name, "error-app-tag")) {
197 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100198 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200199 return EXIT_FAILURE;
200 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200201 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200202 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200203 } else if (!strcmp(child->name, "error-message")) {
204 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100205 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200206 return EXIT_FAILURE;
207 }
208 restr->emsg = read_yin_subnode(ctx, child, "value");
209 if (!restr->emsg) {
210 return EXIT_FAILURE;
211 }
212 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100213 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200214 return EXIT_FAILURE;
215 }
Radek Krejci41726f92015-06-19 13:11:05 +0200216 }
217
218 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200219
220error:
221 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200222}
223
Michal Vasko88c29542015-11-27 14:57:53 +0100224/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
225int
Radek Krejcib8048692015-08-05 13:36:34 +0200226fill_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 +0200227 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200228{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200229 const char *value, *name;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200230 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200231 struct lys_restr **restr;
232 struct lys_type_bit bit;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200233 struct lys_type *type_der;
Radek Krejcifc8d8322016-06-24 11:23:23 +0200234 int i, j, rc, val_set;
Radek Krejcidc008d72016-02-17 13:12:14 +0100235 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200236 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200237 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200238
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200239 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100240 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200241 if (!value) {
242 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200243 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200244
245 i = parse_identifier(value);
246 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100247 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100248 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200249 goto error;
250 }
251 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100252 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200253 if (value[i]) {
254 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100255 name += i;
256 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100257 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100258 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200259 goto error;
260 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200261 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100262 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200263 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200264
Radek Krejci225376f2016-02-16 17:36:22 +0100265 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200266 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100267 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200268 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200269 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100270
271 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200272 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200273 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200274 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100275 ret = EXIT_FAILURE;
276 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200277 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200278 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200279 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200280
Radek Krejcicf509982015-12-15 09:22:44 +0100281 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100282 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100283 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100284 return -1;
285 }
286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200287 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200288 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200289 /* RFC 6020 9.7.4 - bit */
290
291 /* get bit specifications, at least one must be present */
292 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200293 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
294 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100295 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200296 continue;
297 }
298
Radek Krejci994b6f62015-06-18 16:47:27 +0200299 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200300 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200301 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100302 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200303 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200304 }
305 }
Radek Krejciac781922015-07-09 15:35:14 +0200306 if (!type->der->type.der && !type->info.bits.count) {
307 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100308 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200309 goto error;
310 }
Radek Krejciac781922015-07-09 15:35:14 +0200311 if (type->der->type.der && type->info.bits.count) {
312 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100313 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200314 goto error;
315 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200316
317 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100318 if (!type->info.bits.bit) {
319 LOGMEM;
320 goto error;
321 }
Radek Krejci73adb602015-07-02 18:07:40 +0200322 p = 0;
323 i = -1;
324 LY_TREE_FOR(yin->child, next) {
325 i++;
326
327 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100328 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100329 goto error;
330 }
331
Radek Krejci994b6f62015-06-18 16:47:27 +0200332 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200333 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200334 type->info.bits.count = i + 1;
335 goto error;
336 }
337
338 /* check the name uniqueness */
339 for (j = 0; j < i; j++) {
340 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100341 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200342 type->info.bits.count = i + 1;
343 goto error;
344 }
345 }
346
Radek Krejci0d70c372015-07-02 16:23:10 +0200347 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200348 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200349 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
350 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200351 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200352 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200353
Radek Krejci0d70c372015-07-02 16:23:10 +0200354 if (!strcmp(node->name, "position")) {
355 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200356 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200357
358 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200359 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100360 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200361 type->info.bits.count = i + 1;
362 goto error;
363 }
364 type->info.bits.bit[i].pos = (uint32_t)p_;
365
366 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200367 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200368 p = type->info.bits.bit[i].pos;
369 p++;
370 } else {
371 /* check that the value is unique */
372 for (j = 0; j < i; j++) {
373 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100374 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100375 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200376 type->info.bits.count = i + 1;
377 goto error;
378 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200379 }
380 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200381 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100382 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200383 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200384 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200385 }
386 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200387 /* assign value automatically */
388 if (p > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100389 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200390 type->info.bits.count = i + 1;
391 goto error;
392 }
393 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100394 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200395 p++;
396 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200397
398 /* keep them ordered by position */
399 j = i;
400 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
401 /* switch them */
402 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
403 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
404 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
405 j--;
406 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200408 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200410 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200411 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200412 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200413 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
414 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200415 continue;
416 }
417
Radek Krejcif9401c32015-06-26 16:47:36 +0200418 if (!strcmp(node->name, "range")) {
419 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100420 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200421 goto error;
422 }
423
424 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200425 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100426 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200427 goto error;
428 }
429 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100430 if (!type->info.dec64.range) {
431 LOGMEM;
432 goto error;
433 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200434 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
435
436 /* get possible substatements */
437 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
438 goto error;
439 }
440 } else if (!strcmp(node->name, "fraction-digits")) {
441 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100442 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200443 goto error;
444 }
445 GETVAL(value, node, "value");
446 v = strtol(value, NULL, 10);
447
448 /* range check */
449 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100450 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200451 goto error;
452 }
453 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200454 type->info.dec64.div = 10;
455 for (i = 1; i < v; i++) {
456 type->info.dec64.div *= 10;
457 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200458 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100459 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200460 goto error;
461 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200462 }
463
464 /* mandatory sub-statement(s) check */
465 if (!type->info.dec64.dig && !type->der->type.der) {
466 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100467 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200468 goto error;
469 }
Radek Krejci7511f402015-07-10 09:56:30 +0200470 if (type->info.dec64.dig && type->der->type.der) {
471 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100472 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200473 goto error;
474 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200475 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200478 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200479
Radek Krejci994b6f62015-06-18 16:47:27 +0200480 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200481 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200482 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
483 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100484 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200485 continue;
486 }
487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200488 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200490 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100491 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200492 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200493 }
494 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200495 if (!type->der->type.der && !type->info.enums.count) {
496 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100497 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200498 goto error;
499 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200500 if (type->der->type.der && type->info.enums.count) {
501 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100502 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200503 goto error;
504 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200505
Radek Krejci1574a8d2015-08-03 14:16:52 +0200506 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100507 if (!type->info.enums.enm) {
508 LOGMEM;
509 goto error;
510 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200511
512 val_set = v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200513 i = -1;
514 LY_TREE_FOR(yin->child, next) {
515 i++;
516
517 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100518 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100519 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
520 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100521 goto error;
522 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200523 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200524 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525 type->info.enums.count = i + 1;
526 goto error;
527 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200529 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200530 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200531 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100532 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200533 type->info.enums.count = i + 1;
534 goto error;
535 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200537 /* check the name uniqueness */
538 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200539 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100540 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200541 type->info.enums.count = i + 1;
542 goto error;
543 }
544 }
Radek Krejci04581c62015-05-22 21:24:00 +0200545
Radek Krejci73adb602015-07-02 18:07:40 +0200546 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200547 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
548 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200549 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200550 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200551
Radek Krejci0d70c372015-07-02 16:23:10 +0200552 if (!strcmp(node->name, "value")) {
553 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200554 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200555
556 /* range check */
557 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100558 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200559 type->info.enums.count = i + 1;
560 goto error;
561 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200562 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200563
564 /* keep the highest enum value for automatic increment */
Radek Krejcifc8d8322016-06-24 11:23:23 +0200565 if (!val_set || type->info.enums.enm[i].value > v) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200566 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200567 v++;
568 } else {
569 /* check that the value is unique */
570 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200571 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100572 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100573 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200574 type->info.enums.count = i + 1;
575 goto error;
576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200577 }
578 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200579 val_set = 1;
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100581 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200582 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200584 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200585 if (!val_set) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200586 /* assign value automatically */
587 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100588 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 type->info.enums.count = i + 1;
590 goto error;
591 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200592 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100593 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 v++;
595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200596 }
597 break;
598
599 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200600 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200601
602 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200603 LY_TREE_FOR_SAFE(yin->child, next, node) {
604 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
605 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100606 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200607 continue;
608 }
609
Michal Vaskoe29c6622015-11-27 15:02:31 +0100610 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100611 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200612 goto error;
613 }
614 }
615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200616 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200617 if (type->der->type.der) {
618 /* this is just a derived type with no base specified/required */
619 break;
620 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100621 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 goto error;
623 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200624 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100625 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626 goto error;
627 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200628 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100629 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100630 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100631 if (!value) {
632 goto error;
633 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100634 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100635 lydict_remove(module->ctx, value);
636
637 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200638 goto error;
639 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 break;
641
642 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200643 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200644 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200645 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
646 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200647 continue;
648 }
649
Radek Krejciaf351422015-06-19 14:49:38 +0200650 if (!strcmp(node->name, "require-instance")) {
651 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200653 goto error;
654 }
655 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200656 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200657 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200658 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200659 type->info.inst.req = -1;
660 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100661 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200662 goto error;
663 }
664 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100665 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200666 goto error;
667 }
Radek Krejciaf351422015-06-19 14:49:38 +0200668 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200670 break;
671
Radek Krejcif2860132015-06-20 12:37:20 +0200672 case LY_TYPE_BINARY:
673 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 case LY_TYPE_INT8:
675 case LY_TYPE_INT16:
676 case LY_TYPE_INT32:
677 case LY_TYPE_INT64:
678 case LY_TYPE_UINT8:
679 case LY_TYPE_UINT16:
680 case LY_TYPE_UINT32:
681 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200682 /* RFC 6020 9.2.4 - range */
683
684 /* length and range are actually the same restriction, so process
685 * them by this common code, we just need to differ the name and
686 * structure where the information will be stored
687 */
688 if (type->base == LY_TYPE_BINARY) {
689 restr = &type->info.binary.length;
690 name = "length";
691 } else {
692 restr = &type->info.num.range;
693 name = "range";
694 }
695
Radek Krejci73adb602015-07-02 18:07:40 +0200696 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200697 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
698 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200699 continue;
700 }
701
Radek Krejcif2860132015-06-20 12:37:20 +0200702 if (!strcmp(node->name, name)) {
703 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100704 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200705 goto error;
706 }
707
708 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200709 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100710 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200711 goto error;
712 }
713 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100714 if (!(*restr)) {
715 LOGMEM;
716 goto error;
717 }
Radek Krejcif2860132015-06-20 12:37:20 +0200718 (*restr)->expr = lydict_insert(module->ctx, value, 0);
719
720 /* get possible substatements */
721 if (read_restr_substmt(module->ctx, *restr, node)) {
722 goto error;
723 }
724 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100725 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200726 goto error;
727 }
Radek Krejcif2860132015-06-20 12:37:20 +0200728 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 break;
730
731 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200732 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200733 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200734 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
735 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200736 continue;
737 }
738
Michal Vasko88c29542015-11-27 14:57:53 +0100739 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200740 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100741 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200742 goto error;
743 }
744
745 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200746 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100747 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200748 if (!type->info.lref.path) {
749 goto error;
750 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100751 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200752 goto error;
753 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200754
Radek Krejcidc4c1412015-06-19 15:39:54 +0200755 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100756 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200757 goto error;
758 }
Radek Krejci73adb602015-07-02 18:07:40 +0200759 }
760
Michal Vasko88c29542015-11-27 14:57:53 +0100761 if (!type->info.lref.path && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100762 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200763 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200764 } else if (type->der->type.der && parent) {
765 for (type_der = &type->der->type; !type_der->info.lref.path && type_der->der; type_der = &type_der->der->type);
766 assert(type_der->info.lref.path && type_der->info.lref.target);
767 /* add pointer to leafref target, only on leaves (not in typedefs) */
768 if (lys_leaf_add_leafref_target(type_der->info.lref.target, (struct lys_node *)type->parent)) {
769 goto error;
770 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200771 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200772 break;
773
774 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200775 /* RFC 6020 9.4.4 - length */
776 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200777 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200778 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200779 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
780 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100781 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200782 continue;
783 }
784
Radek Krejci3733a802015-06-19 13:43:21 +0200785 if (!strcmp(node->name, "length")) {
786 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100787 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200788 goto error;
789 }
790
791 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200792 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100793 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200794 goto error;
795 }
796 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100797 if (!type->info.str.length) {
798 LOGMEM;
799 goto error;
800 }
Radek Krejci3733a802015-06-19 13:43:21 +0200801 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
802
Radek Krejci5fbc9162015-06-19 14:11:11 +0200803 /* get possible sub-statements */
804 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200805 goto error;
806 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100807 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200808 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200809 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200810 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100811 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200812 goto error;
813 }
814 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200815 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200816 if (i) {
817 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100818 if (!type->info.str.patterns) {
819 LOGMEM;
820 goto error;
821 }
Radek Krejci73adb602015-07-02 18:07:40 +0200822 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100823 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200824
Michal Vasko0aee5c12016-06-17 14:27:26 +0200825 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +0200826 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +0200827 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +0200828 goto error;
829 }
Michal Vasko69068852015-07-13 14:34:31 +0200830
Radek Krejci73adb602015-07-02 18:07:40 +0200831 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200832
833 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100834 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200835 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200836 goto error;
837 }
Radek Krejci73adb602015-07-02 18:07:40 +0200838 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200839 }
840 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841 break;
842
843 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200844 /* RFC 6020 7.4 - type */
845 /* count number of types in union */
846 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200847 LY_TREE_FOR_SAFE(yin->child, next, node) {
848 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
849 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100850 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200851 continue;
852 }
853
Radek Krejcie4c366b2015-07-02 10:11:31 +0200854 if (!strcmp(node->name, "type")) {
855 i++;
856 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100857 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200858 goto error;
859 }
860 }
861
862 if (!i) {
863 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100864 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200865 break;
866 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100867 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200868 goto error;
869 }
870
871 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200872 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100873 if (!type->info.uni.types) {
874 LOGMEM;
875 goto error;
876 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200877 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200878 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100879 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100880 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
881 if (!rc) {
882 type->info.uni.count++;
883
884 /* union's type cannot be empty or leafref */
885 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100886 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100887 rc = -1;
888 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100889 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100890 rc = -1;
891 }
892 }
893 if (rc) {
894 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
895 for (i = 0; i < type->info.uni.count; ++i) {
896 lys_type_free(module->ctx, &type->info.uni.types[i]);
897 }
898 free(type->info.uni.types);
899 type->info.uni.types = NULL;
900 type->info.uni.count = 0;
901
902 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100903 ret = EXIT_FAILURE;
904 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100905 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200906 goto error;
907 }
Michal Vasko88c29542015-11-27 14:57:53 +0100908 }
909 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200910
Michal Vasko88c29542015-11-27 14:57:53 +0100911 case LY_TYPE_BOOL:
912 case LY_TYPE_EMPTY:
913 /* no sub-statement allowed */
914 LY_TREE_FOR(yin->child, node) {
915 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100916 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200917 goto error;
918 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200919 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200920 break;
921
922 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100923 LOGINT;
924 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 }
926
927 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200928
929error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100930 if (type->module_name) {
931 lydict_remove(module->ctx, type->module_name);
932 type->module_name = NULL;
933 }
934 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200935}
936
Michal Vasko0d343d12015-08-24 14:57:36 +0200937/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200939fill_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 +0200940{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100942 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100943 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200945 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100946 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 goto error;
948 }
949 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100952 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 goto error;
954 }
Radek Krejcieac35532015-05-31 19:09:15 +0200955
Michal Vasko88c29542015-11-27 14:57:53 +0100956 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200957 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
958 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200959 continue;
960 }
961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100963 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100964 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 goto error;
966 }
Michal Vasko88c29542015-11-27 14:57:53 +0100967 /* HACK for unres */
968 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100969 tpdf->type.parent = tpdf;
Radek Krejci48464ed2016-03-17 15:44:09 +0100970 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent)) {
Radek Krejci73adb602015-07-02 18:07:40 +0200971 goto error;
972 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200973 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 } else if (!strcmp(node->name, "default")) {
975 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100976 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200977 goto error;
978 }
979 GETVAL(value, node, "value");
980 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
981 } else if (!strcmp(node->name, "units")) {
982 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100983 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 goto error;
985 }
986 GETVAL(value, node, "name");
987 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
988 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100989 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 goto error;
991 }
992 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200995 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100996 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 goto error;
998 }
Radek Krejcieac35532015-05-31 19:09:15 +0200999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001001 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001002 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001003 goto error;
1004 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001005 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001007 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001008
1009error:
1010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001012}
1013
Michal Vasko0d343d12015-08-24 14:57:36 +02001014/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001015static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001016fill_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 +02001017{
1018 const char *value;
1019 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001020 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001021
Radek Krejcib05774c2015-06-18 13:52:59 +02001022 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001023 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001024 goto error;
1025 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001026 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001027 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001028
Radek Krejci76512572015-08-04 09:47:08 +02001029 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001030 goto error;
1031 }
1032
1033 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001034 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1035 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001036 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001037 continue;
1038 }
1039
Radek Krejci3cf9e222015-06-18 11:37:50 +02001040 if (!strcmp(child->name, "if-feature")) {
1041 c++;
1042 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001043 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001044 goto error;
1045 }
1046 }
1047
1048 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001049 f->iffeature = calloc(c, sizeof *f->iffeature);
1050 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001051 LOGMEM;
1052 goto error;
1053 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001054 }
Radek Krejci73adb602015-07-02 18:07:40 +02001055 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001056 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1057 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001058 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001059 goto error;
1060 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001061 }
1062
Radek Krejci3cf9e222015-06-18 11:37:50 +02001063 return EXIT_SUCCESS;
1064
1065error:
1066
1067 return EXIT_FAILURE;
1068}
1069
Michal Vasko0d343d12015-08-24 14:57:36 +02001070/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071static int
Radek Krejcib8048692015-08-05 13:36:34 +02001072fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001073{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001077 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001078 if (!must->expr) {
1079 goto error;
1080 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001081 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001082 goto error;
1083 }
Radek Krejci800af702015-06-02 13:46:01 +02001084
Radek Krejci41726f92015-06-19 13:11:05 +02001085 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001086
Michal Vasko77dc5652016-02-15 12:32:42 +01001087error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001089}
1090
Radek Krejci581ce772015-11-10 17:22:40 +01001091static int
Michal Vasko88c29542015-11-27 14:57:53 +01001092fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1093 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001094{
1095 int i, j;
1096 const char *value, *vaux;
1097
1098 /* get unique value (list of leafs supposed to be unique */
1099 GETVAL(value, yin, "tag");
1100
1101 /* count the number of unique leafs in the value */
1102 vaux = value;
1103 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001104 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001105 while (isspace(*vaux)) {
1106 vaux++;
1107 }
1108 }
1109 unique->expr_size++;
1110 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001111 if (!unique->expr) {
1112 LOGMEM;
1113 goto error;
1114 }
Radek Krejci581ce772015-11-10 17:22:40 +01001115
1116 for (i = 0; i < unique->expr_size; i++) {
1117 vaux = strpbrk(value, " \t\n");
1118 if (!vaux) {
1119 /* the last token, lydict_insert() will count its size on its own */
1120 vaux = value;
1121 }
1122
1123 /* store token into unique structure */
1124 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1125
1126 /* check that the expression does not repeat */
1127 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001128 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001129 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001131 goto error;
1132 }
1133 }
1134
1135 /* try to resolve leaf */
1136 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001137 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1138 goto error;
1139 }
Radek Krejci581ce772015-11-10 17:22:40 +01001140 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001141 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001142 goto error;
1143 }
1144 }
1145
1146 /* move to next token */
1147 value = vaux;
1148 while(isspace(*value)) {
1149 value++;
1150 }
1151 }
1152
1153 return EXIT_SUCCESS;
1154
1155error:
1156 return EXIT_FAILURE;
1157}
1158
Michal Vasko0d343d12015-08-24 14:57:36 +02001159/* logs directly
1160 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001161 * type: 0 - min, 1 - max
1162 */
1163static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001164deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001165{
1166 const char *value;
1167 char *endptr;
1168 unsigned long val;
1169 uint32_t *ui32val;
1170
Michal Vaskof7e57d52016-03-07 11:31:09 +01001171 /* del min/max is forbidden */
1172 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001173 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001174 goto error;
1175 }
1176
Radek Krejcieb00f512015-07-01 16:44:58 +02001177 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001178 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001179 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001180 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001181 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001182 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001183 }
Radek Krejci76512572015-08-04 09:47:08 +02001184 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001185 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001186 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001187 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001188 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001189 }
1190 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001191 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1192 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001193 goto error;
1194 }
1195
1196 GETVAL(value, node, "value");
1197 while (isspace(value[0])) {
1198 value++;
1199 }
1200
Radek Krejci0d7b2472016-02-12 11:11:03 +01001201 if (type && !strcmp(value, "unbounded")) {
1202 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001203 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001204 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001205 /* convert it to uint32_t */
1206 errno = 0;
1207 endptr = NULL;
1208 val = strtoul(value, &endptr, 10);
1209 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001210 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001211 goto error;
1212 }
1213 if (type) {
1214 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001215 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001216 } else {
1217 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001218 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001219 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001220 }
1221
1222 if (d->mod == LY_DEVIATE_ADD) {
1223 /* check that there is no current value */
1224 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001225 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1226 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001227 goto error;
1228 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001229 } else if (d->mod == LY_DEVIATE_RPL) {
1230 /* unfortunately, there is no way to check reliably that there
1231 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001232 }
1233
Michal Vaskof7e57d52016-03-07 11:31:09 +01001234 /* add (already checked) and replace */
1235 /* set new value specified in deviation */
1236 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001237
1238 return EXIT_SUCCESS;
1239
1240error:
1241
1242 return EXIT_FAILURE;
1243}
1244
Michal Vasko0d343d12015-08-24 14:57:36 +02001245/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001246static int
Michal Vasko88c29542015-11-27 14:57:53 +01001247fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1248 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001249{
1250 const char *value, **stritem;
1251 struct lyxml_elem *next, *child, *develem;
1252 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001253 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001254 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001255 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001256 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001257 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001258 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001259 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001260 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001261 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001262 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001263 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001264 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001265
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001266 ctx = module->ctx;
1267
Radek Krejcieb00f512015-07-01 16:44:58 +02001268 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001269 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001270 if (!dev->target_name) {
1271 goto error;
1272 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001273
1274 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001275 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1276 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001277 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001278 goto error;
1279 }
Radek Krejcic4283442016-04-22 09:19:27 +02001280 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001281 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1282 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001283 goto error;
1284 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001285 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001286
1287 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001288 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1289 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001290 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001291 continue;
1292 }
1293
Radek Krejcieb00f512015-07-01 16:44:58 +02001294 if (!strcmp(child->name, "description")) {
1295 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001296 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001297 goto error;
1298 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001299 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001300 if (!dev->dsc) {
1301 goto error;
1302 }
1303 } else if (!strcmp(child->name, "reference")) {
1304 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001305 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001306 goto error;
1307 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001308 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001309 if (!dev->ref) {
1310 goto error;
1311 }
1312 } else if (!strcmp(child->name, "deviate")) {
1313 c_dev++;
1314
Michal Vasko345da0a2015-12-02 10:35:55 +01001315 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001316 * further processed later
1317 */
1318 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001319
Radek Krejcieb00f512015-07-01 16:44:58 +02001320 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001321 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001322 goto error;
1323 }
1324
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001325 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001326 }
1327
1328 if (c_dev) {
1329 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001330 if (!dev->deviate) {
1331 LOGMEM;
1332 goto error;
1333 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001334 }
1335
1336 LY_TREE_FOR(yin->child, develem) {
1337 /* init */
1338 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001339 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001340 c_must = 0;
1341 c_uniq = 0;
1342
1343 /* get deviation type */
1344 GETVAL(value, develem, "value");
1345 if (!strcmp(value, "not-supported")) {
1346 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1347 /* no property expected in this case */
1348 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001349 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001350 goto error;
1351 }
1352
Radek Krejci5b917642015-07-02 09:03:13 +02001353 /* and neither any other deviate statement is expected,
1354 * not-supported deviation must be the only deviation of the target
1355 */
1356 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001357 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1358 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001359 goto error;
1360 }
1361
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001362 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001363 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1364 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1365 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001366 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1367 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001368 goto error;
1369 }
1370 }
1371 }
Radek Krejci5b917642015-07-02 09:03:13 +02001372
Michal Vaskoff006c12016-02-17 11:15:19 +01001373 /* unlink and store the original node */
1374 lys_node_unlink(dev_target);
1375 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001376
Radek Krejci5b917642015-07-02 09:03:13 +02001377 dev->deviate_size = 1;
1378 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001379 } else if (!strcmp(value, "add")) {
1380 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1381 } else if (!strcmp(value, "replace")) {
1382 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1383 } else if (!strcmp(value, "delete")) {
1384 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1385 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001386 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001387 goto error;
1388 }
1389 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001390 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001391
Michal Vaskoff006c12016-02-17 11:15:19 +01001392 /* store a shallow copy of the original node */
1393 if (!dev->orig_node) {
1394 memset(&tmp_unres, 0, sizeof tmp_unres);
1395 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1396 /* just to be safe */
1397 if (tmp_unres.count) {
1398 LOGINT;
1399 goto error;
1400 }
1401 }
1402
Radek Krejcieb00f512015-07-01 16:44:58 +02001403 /* process deviation properties */
1404 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001405 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1406 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001407 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001408 continue;
1409 }
1410
Radek Krejcieb00f512015-07-01 16:44:58 +02001411 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001412 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001413 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001414 goto error;
1415 }
1416
1417 /* for we deviate from RFC 6020 and allow config property even it is/is not
1418 * specified in the target explicitly since config property inherits. So we expect
1419 * that config is specified in every node. But for delete, we check that the value
1420 * is the same as here in deviation
1421 */
1422 GETVAL(value, child, "value");
1423 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001424 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001425 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001426 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001427 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001428 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001429 goto error;
1430 }
1431
1432 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001433 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001434 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001435 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001436 } else { /* add and replace are the same in this case */
1437 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001438 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001439
1440 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001441 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001442 }
1443 } else if (!strcmp(child->name, "default")) {
1444 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001445 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001446 goto error;
1447 }
1448 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001449 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001450
Michal Vasko60f4b452016-02-12 11:02:55 +01001451 if (dev_target->nodetype == LYS_CHOICE) {
1452 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001453
1454 if (d->mod == LY_DEVIATE_ADD) {
1455 /* check that there is no current value */
1456 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001457 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1458 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001459 goto error;
1460 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001461 /* check collision with mandatory */
1462 if (choice->flags & LYS_MAND_TRUE) {
1463 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1464 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1465 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1466 goto error;
1467 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001468 } else if (d->mod == LY_DEVIATE_RPL) {
1469 /* check that there was a value before */
1470 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001471 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1472 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001473 goto error;
1474 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001475 }
1476
Michal Vasko3edeaf72016-02-11 13:17:43 +01001477 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001478 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001479 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001480 goto error;
1481 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001482 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001483 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001484 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1485 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 goto error;
1487 }
1488 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001489 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001490 if (!choice->dflt) {
1491 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001492 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001493 goto error;
1494 }
1495 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001496 } else if (dev_target->nodetype == LYS_LEAF) {
1497 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001498
1499 if (d->mod == LY_DEVIATE_ADD) {
1500 /* check that there is no current value */
1501 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001502 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1503 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001504 goto error;
1505 }
Radek Krejci841ec082016-04-05 13:05:17 +02001506 /* check collision with mandatory */
1507 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001508 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001509 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001510 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001511 goto error;
1512 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 }
1514
1515 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001516 if (!leaf->dflt || !ly_strequal(leaf->dflt, d->dflt, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001517 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1518 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 goto error;
1520 }
1521 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001522 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001523 leaf->dflt = NULL;
1524 } else { /* add (already checked) and replace */
1525 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001526 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001527
1528 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001529 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001530
1531 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1532 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1533 if (!leaf_dflt_check) {
1534 LOGMEM;
1535 goto error;
1536 }
1537 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001538 }
1539 } else {
1540 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001541 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1542 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 goto error;
1544 }
1545 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001546 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001547 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001548 goto error;
1549 }
1550
1551 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001552 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001553 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1554 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 goto error;
1556 }
1557
1558 GETVAL(value, child, "value");
1559 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001560 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001561 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001562 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001564 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001565 goto error;
1566 }
1567
1568 if (d->mod == LY_DEVIATE_ADD) {
1569 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001570 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001571 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1572 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001573 goto error;
1574 }
Radek Krejci841ec082016-04-05 13:05:17 +02001575 /* check collision with default-stmt */
1576 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001577 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001578 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001579 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001580 goto error;
1581 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001582
Michal Vasko21be1b32016-03-07 12:31:34 +01001583 dev_target->flags |= d->flags & LYS_MAND_MASK;
1584 } else if (d->mod == LY_DEVIATE_RPL) {
1585 /* check that there was a value before */
1586 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001587 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1588 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001589 goto error;
1590 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001591
Michal Vasko21be1b32016-03-07 12:31:34 +01001592 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001593 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001594 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001595 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001596 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001597 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001598 }
1599 } else if (!strcmp(child->name, "min-elements")) {
1600 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001601 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001602 goto error;
1603 }
1604 f_min = 1;
1605
Michal Vasko60f4b452016-02-12 11:02:55 +01001606 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001607 goto error;
1608 }
1609 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001610 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001611 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001612 goto error;
1613 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001614 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001615
Michal Vasko60f4b452016-02-12 11:02:55 +01001616 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001617 goto error;
1618 }
1619 } else if (!strcmp(child->name, "must")) {
1620 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001621 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 continue;
1623 } else if (!strcmp(child->name, "type")) {
1624 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001625 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001626 goto error;
1627 }
1628
Michal Vaskof7e57d52016-03-07 11:31:09 +01001629 /* add, del type is forbidden */
1630 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001631 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001632 goto error;
1633 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001634 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001635 goto error;
1636 }
1637
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001639 if (dev_target->nodetype == LYS_LEAF) {
1640 t = &((struct lys_node_leaf *)dev_target)->type;
1641 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1642 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001643 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001644 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1645 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 goto error;
1647 }
1648
Radek Krejcieb00f512015-07-01 16:44:58 +02001649 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001650 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001651 /* HACK for unres */
1652 t->der = (struct lys_tpdf *)child;
Radek Krejci48464ed2016-03-17 15:44:09 +01001653 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001654 goto error;
1655 }
1656 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001657
1658 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1659 if (dev_target->nodetype == LYS_LEAF) {
1660 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1661 if (!leaf_dflt_check) {
1662 LOGMEM;
1663 goto error;
1664 }
1665 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1666 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 } else if (!strcmp(child->name, "unique")) {
1668 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001669 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001670 continue;
1671 } else if (!strcmp(child->name, "units")) {
1672 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001673 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001674 goto error;
1675 }
1676
1677 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001678 if (dev_target->nodetype == LYS_LEAFLIST) {
1679 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1680 } else if (dev_target->nodetype == LYS_LEAF) {
1681 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001683 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1684 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001685 goto error;
1686 }
1687
1688 /* get units value */
1689 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001690 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001691
1692 /* apply to target */
1693 if (d->mod == LY_DEVIATE_ADD) {
1694 /* check that there is no current value */
1695 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001696 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1697 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001698 goto error;
1699 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001700
Michal Vasko21be1b32016-03-07 12:31:34 +01001701 *stritem = lydict_insert(ctx, value, 0);
1702 } else if (d->mod == LY_DEVIATE_RPL) {
1703 /* check that there was a value before */
1704 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001705 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1706 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001707 goto error;
1708 }
1709
1710 lydict_remove(ctx, *stritem);
1711 *stritem = lydict_insert(ctx, value, 0);
1712 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001714 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001715 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1716 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001717 goto error;
1718 }
1719 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001720 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001721 }
1722 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001723 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001724 goto error;
1725 }
1726
Michal Vasko88c29542015-11-27 14:57:53 +01001727 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001728 }
1729
1730 if (c_must) {
1731 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001732 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001733 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001734 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1735 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001736 break;
Radek Krejci76512572015-08-04 09:47:08 +02001737 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001738 trg_must = &((struct lys_node_container *)dev_target)->must;
1739 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001740 break;
Radek Krejci76512572015-08-04 09:47:08 +02001741 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001742 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1743 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001744 break;
Radek Krejci76512572015-08-04 09:47:08 +02001745 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001746 trg_must = &((struct lys_node_list *)dev_target)->must;
1747 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001748 break;
Radek Krejci76512572015-08-04 09:47:08 +02001749 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001750 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1751 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001752 break;
1753 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001754 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1755 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 goto error;
1757 }
1758
1759 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001760 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001761 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001762 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001763 } else if (d->mod == LY_DEVIATE_ADD) {
1764 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001765 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001766 if (!d->must) {
1767 LOGMEM;
1768 goto error;
1769 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001770 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001771 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001772 d->must_size = c_must;
1773 } else { /* LY_DEVIATE_DEL */
1774 d->must = calloc(c_must, sizeof *d->must);
1775 }
Michal Vasko253035f2015-12-17 16:58:13 +01001776 if (!d->must) {
1777 LOGMEM;
1778 goto error;
1779 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001780 }
1781 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001782 /* replace unique is forbidden */
1783 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001784 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001785 goto error;
1786 }
1787
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001789 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001790 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1791 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001792 goto error;
1793 }
1794
Michal Vasko60f4b452016-02-12 11:02:55 +01001795 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001796 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001797 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001798 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001799 list->unique = d->unique;
1800 d->unique = &list->unique[list->unique_size];
1801 d->unique_size = c_uniq;
1802 } else { /* LY_DEVIATE_DEL */
1803 d->unique = calloc(c_uniq, sizeof *d->unique);
1804 }
Michal Vasko253035f2015-12-17 16:58:13 +01001805 if (!d->unique) {
1806 LOGMEM;
1807 goto error;
1808 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001809 }
1810
1811 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001812 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001813 if (!strcmp(child->name, "must")) {
1814 if (d->mod == LY_DEVIATE_DEL) {
1815 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1816 goto error;
1817 }
1818
1819 /* find must to delete, we are ok with just matching conditions */
1820 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001821 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001822 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001823 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 /* ... and maintain the array */
1825 (*trg_must_size)--;
1826 if (i != *trg_must_size) {
1827 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1828 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1829 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1830 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1831 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1832 }
1833 if (!(*trg_must_size)) {
1834 free(*trg_must);
1835 *trg_must = NULL;
1836 } else {
1837 (*trg_must)[*trg_must_size].expr = NULL;
1838 (*trg_must)[*trg_must_size].dsc = NULL;
1839 (*trg_must)[*trg_must_size].ref = NULL;
1840 (*trg_must)[*trg_must_size].eapptag = NULL;
1841 (*trg_must)[*trg_must_size].emsg = NULL;
1842 }
1843
1844 i = -1; /* set match flag */
1845 break;
1846 }
1847 }
1848 d->must_size++;
1849 if (i != -1) {
1850 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001851 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001852 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001853 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001854 goto error;
1855 }
1856 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001857 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1858 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001859 goto error;
1860 }
1861 (*trg_must_size)++;
1862 }
1863 } else if (!strcmp(child->name, "unique")) {
1864 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001865 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001866 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001867 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001868 goto error;
1869 }
1870
1871 /* find unique structures to delete */
1872 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001873 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001874 continue;
1875 }
1876
Radek Krejci581ce772015-11-10 17:22:40 +01001877 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001878 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001879 break;
1880 }
1881 }
1882
Radek Krejci581ce772015-11-10 17:22:40 +01001883 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001884 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001885 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001886 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001887 }
1888 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001889 /* ... and maintain the array */
1890 list->unique_size--;
1891 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001892 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1893 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001894 }
1895
1896 if (!list->unique_size) {
1897 free(list->unique);
1898 list->unique = NULL;
1899 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001900 list->unique[list->unique_size].expr_size = 0;
1901 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001902 }
1903
1904 i = -1; /* set match flag */
1905 break;
1906 }
1907 }
1908
1909 d->unique_size++;
1910 if (i != -1) {
1911 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001912 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1913 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001914 goto error;
1915 }
1916 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001917 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001918 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001919 list->unique_size++;
1920 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001921 goto error;
1922 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 }
1924 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001925 }
1926 }
1927
Michal Vasko43a1feb2016-03-07 12:03:02 +01001928 /* now check whether default value, if any, matches the type */
1929 for (i = 0; i < leaf_dflt_check_count; ++i) {
1930 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001931 rc = unres_schema_add_str(module, unres, &leaf_dflt_check[i]->type, UNRES_TYPE_DFLT, leaf_dflt_check[i]->dflt);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001932 if (rc == -1) {
1933 goto error;
1934 } else if (rc == EXIT_FAILURE) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001935 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1936 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->target_name);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001937 goto error;
1938 }
1939 }
1940 }
1941 free(leaf_dflt_check);
1942
Radek Krejcieb00f512015-07-01 16:44:58 +02001943 return EXIT_SUCCESS;
1944
1945error:
Michal Vasko34867132016-03-11 10:26:38 +01001946 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001947 return EXIT_FAILURE;
1948}
1949
Michal Vasko0d343d12015-08-24 14:57:36 +02001950/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001951static int
Radek Krejcib8048692015-08-05 13:36:34 +02001952fill_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 +02001953 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001954{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001956 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001957 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001958 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001959
Michal Vasko591e0b22015-08-13 13:53:43 +02001960 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001962 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02001963 if (!aug->target_name) {
1964 goto error;
1965 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001967
Michal Vasko1d87a922015-08-21 12:57:16 +02001968 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001969 goto error;
1970 }
1971
1972 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001973 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1974 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001975 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001976 continue;
1977 }
1978
Radek Krejci3cf9e222015-06-18 11:37:50 +02001979 if (!strcmp(child->name, "if-feature")) {
1980 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001981 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001982 } else if (!strcmp(child->name, "when")) {
1983 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001984 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001985 goto error;
1986 }
1987
1988 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001989 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001990 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001991 goto error;
1992 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001993 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001995
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001996 /* check allowed data sub-statements */
1997 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001998 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002006 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002007 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002008 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002010 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002012 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002013 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002014 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002015 goto error;
2016 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017
Radek Krejci1d82ef62015-08-07 14:44:40 +02002018 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002019 goto error;
2020 }
2021
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002023 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002024 }
2025
2026 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002027 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2028 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002029 LOGMEM;
2030 goto error;
2031 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002032 }
2033
2034 LY_TREE_FOR_SAFE(yin->child, next, child) {
2035 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002036 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2037 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002038 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002039 goto error;
2040 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002041 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002042 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002043 }
2044
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002045 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002046 * connected to the tree and adjusted (if possible right now).
2047 * However, if this is augment in a uses, it gets resolved
2048 * when the uses does and cannot be resolved now for sure
2049 * (the grouping was not yet copied into uses).
2050 */
2051 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002052 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002053 goto error;
2054 }
Michal Vasko49291b32015-08-06 09:49:41 +02002055 }
Radek Krejci106efc02015-06-10 14:36:27 +02002056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002057 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002058
2059error:
2060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002062}
2063
Michal Vasko0d343d12015-08-24 14:57:36 +02002064/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065static int
Michal Vasko0d204592015-10-07 09:50:04 +02002066fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002067{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 struct lyxml_elem *sub, *next;
2069 const char *value;
2070 char *endptr;
2071 int f_mand = 0, f_min = 0, f_max = 0;
2072 int c_must = 0;
2073 int r;
2074 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002075
Radek Krejci76512572015-08-04 09:47:08 +02002076 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 goto error;
2078 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002079
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002080 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002081 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002082 if (!rfn->target_name) {
2083 goto error;
2084 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002087 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2088 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002089 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002090 continue;
2091 }
2092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 /* limited applicability */
2094 if (!strcmp(sub->name, "default")) {
2095 /* leaf or choice */
2096 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002097 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 goto error;
2099 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 /* check possibility of statements combination */
2102 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002103 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002105 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2106 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 goto error;
2108 }
2109 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002110 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 GETVAL(value, sub, "value");
2114 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2115 } else if (!strcmp(sub->name, "mandatory")) {
2116 /* leaf, choice or anyxml */
2117 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002118 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 goto error;
2120 }
2121 /* just checking the flags in leaf is not sufficient, we would allow
2122 * multiple mandatory statements with the "false" value
2123 */
2124 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 /* check possibility of statements combination */
2127 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002128 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002130 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2131 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 goto error;
2133 }
2134 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002135 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 GETVAL(value, sub, "value");
2139 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002140 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002142 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002144 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 goto error;
2146 }
2147 } else if (!strcmp(sub->name, "min-elements")) {
2148 /* list or leaf-list */
2149 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002150 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 goto error;
2152 }
2153 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 /* check possibility of statements combination */
2156 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002157 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002159 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2160 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 goto error;
2162 }
2163 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002164 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 GETVAL(value, sub, "value");
2168 while (isspace(value[0])) {
2169 value++;
2170 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 /* convert it to uint32_t */
2173 errno = 0;
2174 endptr = NULL;
2175 val = strtoul(value, &endptr, 10);
2176 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002177 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 goto error;
2179 }
2180 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002181 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 } else if (!strcmp(sub->name, "max-elements")) {
2183 /* list or leaf-list */
2184 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002185 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 goto error;
2187 }
2188 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 /* check possibility of statements combination */
2191 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002192 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002194 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2195 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 goto error;
2197 }
2198 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002199 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 GETVAL(value, sub, "value");
2203 while (isspace(value[0])) {
2204 value++;
2205 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002206
Radek Krejci0d7b2472016-02-12 11:11:03 +01002207 if (!strcmp(value, "unbounded")) {
2208 rfn->mod.list.max = 0;
2209 } else {
2210 /* convert it to uint32_t */
2211 errno = 0;
2212 endptr = NULL;
2213 val = strtoul(value, &endptr, 10);
2214 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002215 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002216 goto error;
2217 }
2218 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002220 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 } else if (!strcmp(sub->name, "presence")) {
2222 /* container */
2223 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 goto error;
2226 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 /* check possibility of statements combination */
2229 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002230 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002232 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2233 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 goto error;
2235 }
2236 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002237 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 GETVAL(value, sub, "value");
2241 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2242 } else if (!strcmp(sub->name, "must")) {
2243 /* leaf-list, list, container or anyxml */
2244 /* check possibility of statements combination */
2245 if (rfn->target_type) {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002246 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002248 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2249 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 goto error;
2251 }
2252 } else {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002253 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002257 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002260 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002261 goto error;
2262 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002263
Michal Vasko345da0a2015-12-02 10:35:55 +01002264 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002267 /* process nodes with cardinality of 0..n */
2268 if (c_must) {
2269 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002270 if (!rfn->must) {
2271 LOGMEM;
2272 goto error;
2273 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 }
Radek Krejci73adb602015-07-02 18:07:40 +02002275 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002276 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2277 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002278 if (r) {
2279 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002284
2285error:
2286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002288}
2289
Michal Vasko0d343d12015-08-24 14:57:36 +02002290/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291static int
Radek Krejcib8048692015-08-05 13:36:34 +02002292fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002293{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 struct lyxml_elem *child;
2295 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002298 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2299 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002300 continue;
2301 }
2302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 if (!strcmp(child->name, "prefix")) {
2304 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002305 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 goto error;
2307 }
2308 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2309 } else if (!strcmp(child->name, "revision-date")) {
2310 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002311 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2312 goto error;
2313 } else if (!imp->prefix) {
2314 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2315 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2316 "The \"prefix\" statement is expected before the \"revision-date\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 goto error;
2318 }
2319 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002320 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 goto error;
2322 }
2323 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2324 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002325 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 goto error;
2327 }
2328 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 /* check mandatory information */
2331 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002332 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002333 goto error;
2334 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002336 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002337
Pavol Vicane994fda2016-03-22 10:47:58 +01002338 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002339
2340error:
2341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002343}
2344
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002345/* logs directly
2346 * returns:
2347 * 0 - inc successfully filled
2348 * -1 - error, inc is cleaned
2349 * 1 - duplication, ignore the inc structure, inc is cleaned
2350 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002352fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2353 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002354{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 struct lyxml_elem *child;
2356 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002359 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2360 /* garbage */
2361 continue;
2362 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363 if (!strcmp(child->name, "revision-date")) {
2364 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002365 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 goto error;
2367 }
2368 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002369 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002370 goto error;
2371 }
2372 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2373 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002374 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 goto error;
2376 }
2377 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002379 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002380
Pavol Vican0adf01d2016-03-22 12:29:33 +01002381 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002382
2383error:
2384
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002385 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002386}
2387
Michal Vasko0d343d12015-08-24 14:57:36 +02002388/* logs directly
2389 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002390 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002391 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002392 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002393 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394static int
Radek Krejcib8048692015-08-05 13:36:34 +02002395read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002396 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002397{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 const char *value;
2399 struct lyxml_elem *sub, *next;
2400 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002402 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002403 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 if (opt & OPT_IDENT) {
2407 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002408 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002409 goto error;
2410 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002411 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002413
Radek Krejci6764bb32015-07-03 15:16:04 +02002414 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002415 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002416 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002417 }
2418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 /* process local parameters */
2420 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002421 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002422 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002423 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002424 continue;
2425 }
2426 if (strcmp(sub->ns->value, LY_NSYIN)) {
2427 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002428 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002429 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002430 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002431 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002432 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002433 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002434 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002435 goto error;
2436 }
2437 }
2438
2439 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002440 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002441 continue;
2442 }
2443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002444 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002445 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002446 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002447 goto error;
2448 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002449 node->dsc = read_yin_subnode(ctx, sub, "text");
2450 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002451 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 }
2453 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002454 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002455 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 goto error;
2457 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002458 node->ref = read_yin_subnode(ctx, sub, "text");
2459 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002460 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002461 }
2462 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002463 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002464 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 goto error;
2466 }
2467 GETVAL(value, sub, "value");
2468 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002469 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002471 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002472 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002473 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002474 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002475 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002476 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 }
2478 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002479 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002480 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 goto error;
2482 }
2483 GETVAL(value, sub, "value");
2484 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002487 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002488 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002489 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002490 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002492 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002494 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 continue;
2496 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002497 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002498 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002499
Radek Krejci1d82ef62015-08-07 14:44:40 +02002500 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002502 if (parent && (parent->flags & LYS_CONFIG_R)) {
2503 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504 } else {
2505 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002506 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002507 }
2508 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002511
2512error:
2513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002514 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002515}
2516
Michal Vasko0d343d12015-08-24 14:57:36 +02002517/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002518static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002519read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002520{
Radek Krejci76512572015-08-04 09:47:08 +02002521 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002522 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002523 const char *value;
2524
2525 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002526 if (!retval) {
2527 LOGMEM;
2528 return NULL;
2529 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002530
2531 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002532 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002533 if (!retval->cond) {
2534 goto error;
2535 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002536 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002537 goto error;
2538 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002539
Radek Krejci73adb602015-07-02 18:07:40 +02002540 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002541 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2542 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002543 continue;
2544 }
2545
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002546 if (!strcmp(child->name, "description")) {
2547 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002548 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002549 goto error;
2550 }
2551 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2552 if (!retval->dsc) {
2553 goto error;
2554 }
2555 } else if (!strcmp(child->name, "reference")) {
2556 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002557 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002558 goto error;
2559 }
2560 retval->ref = read_yin_subnode(module->ctx, child, "text");
2561 if (!retval->ref) {
2562 goto error;
2563 }
2564 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002565 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002566 goto error;
2567 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002568 }
2569
2570 return retval;
2571
2572error:
2573
Michal Vasko0308dd62015-10-07 09:14:40 +02002574 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002575 return NULL;
2576}
2577
Michal Vasko0d343d12015-08-24 14:57:36 +02002578/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002579static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002580read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2581 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002582{
Michal Vasko29fc0182015-08-24 15:02:39 +02002583 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002584 struct lys_node_case *cs;
2585 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002586 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002587
Radek Krejcie867c852015-08-27 09:52:34 +02002588 /* init */
2589 memset(&root, 0, sizeof root);
2590
Radek Krejci1d82ef62015-08-07 14:44:40 +02002591 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002592 if (!cs) {
2593 LOGMEM;
2594 return NULL;
2595 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002596 cs->nodetype = LYS_CASE;
2597 cs->prev = (struct lys_node *)cs;
2598 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002599
Radek Krejci6a113852015-07-03 16:04:20 +02002600 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002601 goto error;
2602 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002603
Radek Krejcia9544502015-08-14 08:24:29 +02002604 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2605
Michal Vasko3a0043f2015-08-12 12:11:30 +02002606 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002607 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002608 goto error;
2609 }
2610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 /* process choice's specific children */
2612 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002613 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2614 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002615 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002616 continue;
2617 }
2618
Michal Vasko29fc0182015-08-24 15:02:39 +02002619 if (!strcmp(sub->name, "container") ||
2620 !strcmp(sub->name, "leaf-list") ||
2621 !strcmp(sub->name, "leaf") ||
2622 !strcmp(sub->name, "list") ||
2623 !strcmp(sub->name, "uses") ||
2624 !strcmp(sub->name, "choice") ||
2625 !strcmp(sub->name, "anyxml")) {
2626
Michal Vaskof3930de2015-10-22 12:03:59 +02002627 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002628 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002629 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002630 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002631 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002632 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002633 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002634 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002635 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002636 goto error;
2637 }
2638
Radek Krejci1d82ef62015-08-07 14:44:40 +02002639 cs->when = read_yin_when(module, sub);
2640 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002641 goto error;
2642 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002643
Michal Vasko345da0a2015-12-02 10:35:55 +01002644 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002646 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002650
Radek Krejci3cf9e222015-06-18 11:37:50 +02002651 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002652 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
2653 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002654 LOGMEM;
2655 goto error;
2656 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002657 }
Radek Krejci73adb602015-07-02 18:07:40 +02002658 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002659 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
2660 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002661 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002662 goto error;
2663 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002664 }
Radek Krejcib388c152015-06-04 17:03:03 +02002665
Michal Vasko29fc0182015-08-24 15:02:39 +02002666 /* last part - process data nodes */
2667 LY_TREE_FOR_SAFE(root.child, next, sub) {
2668 if (!strcmp(sub->name, "container")) {
2669 node = read_yin_container(module, retval, sub, resolve, unres);
2670 } else if (!strcmp(sub->name, "leaf-list")) {
2671 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2672 } else if (!strcmp(sub->name, "leaf")) {
2673 node = read_yin_leaf(module, retval, sub, resolve, unres);
2674 } else if (!strcmp(sub->name, "list")) {
2675 node = read_yin_list(module, retval, sub, resolve, unres);
2676 } else if (!strcmp(sub->name, "choice")) {
2677 node = read_yin_choice(module, retval, sub, resolve, unres);
2678 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002679 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02002680 } else if (!strcmp(sub->name, "anyxml")) {
2681 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2682 }
2683 if (!node) {
2684 goto error;
2685 }
2686
Michal Vasko345da0a2015-12-02 10:35:55 +01002687 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002688 }
2689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002691
2692error:
2693
Michal Vasko29fc0182015-08-24 15:02:39 +02002694 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002695 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002696 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002697 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002699 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002700}
2701
Michal Vasko0d343d12015-08-24 14:57:36 +02002702/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002703static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002704read_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 +02002705{
Radek Krejci629cdef2016-06-06 15:06:36 +02002706 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002707 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002708 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002709 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02002710 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02002711 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002714 if (!choice) {
2715 LOGMEM;
2716 return NULL;
2717 }
Radek Krejci76512572015-08-04 09:47:08 +02002718 choice->nodetype = LYS_CHOICE;
2719 choice->prev = (struct lys_node *)choice;
2720 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002721
Michal Vaskoe0c59842015-09-24 13:52:20 +02002722 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2723 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 goto error;
2725 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002726
Radek Krejcia9544502015-08-14 08:24:29 +02002727 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2728
Michal Vasko3a0043f2015-08-12 12:11:30 +02002729 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002730 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002731 goto error;
2732 }
2733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002734 /* process choice's specific children */
2735 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002736 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2737 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002738 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002739 continue;
2740 }
2741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002742 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002743 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002744 goto error;
2745 }
2746 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002747 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 goto error;
2749 }
2750 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002751 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002752 goto error;
2753 }
2754 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002755 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002756 goto error;
2757 }
2758 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002759 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002760 goto error;
2761 }
2762 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002763 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 goto error;
2765 }
2766 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02002767 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002768 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 goto error;
2770 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002771 dflt = sub;
2772 lyxml_unlink_elem(ctx, dflt, 0);
2773
Radek Krejcif9a312c2016-06-06 15:14:30 +02002774 continue;
2775 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
2776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002777 } else if (!strcmp(sub->name, "mandatory")) {
2778 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002779 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002780 goto error;
2781 }
2782 /* just checking the flags in leaf is not sufficient, we would allow
2783 * multiple mandatory statements with the "false" value
2784 */
2785 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 GETVAL(value, sub, "value");
2788 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002789 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002790 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002791 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002792 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002793 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002794 goto error;
2795 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002796 } else if (!strcmp(sub->name, "when")) {
2797 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002798 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002799 goto error;
2800 }
2801
2802 choice->when = read_yin_when(module, sub);
2803 if (!choice->when) {
2804 goto error;
2805 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002806 } else if (!strcmp(sub->name, "if-feature")) {
2807 c_ftrs++;
2808
Michal Vasko345da0a2015-12-02 10:35:55 +01002809 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002810 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002811 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002812 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002813 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002815
Radek Krejci1d82ef62015-08-07 14:44:40 +02002816 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002817 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002819
Radek Krejci3cf9e222015-06-18 11:37:50 +02002820 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002821 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
2822 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002823 LOGMEM;
2824 goto error;
2825 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002826 }
2827
Radek Krejci73adb602015-07-02 18:07:40 +02002828 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002829 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
2830 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002831 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002832 goto error;
2833 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002834 }
2835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02002837 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002838 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2839 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 goto error;
2841 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002843 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02002844 if (dflt) {
2845 GETVAL(value, dflt, "value");
2846 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002847 goto error;
2848 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002849 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002852 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002853
2854error:
2855
Radek Krejci629cdef2016-06-06 15:06:36 +02002856 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002857 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002859 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002860}
2861
Michal Vasko0d343d12015-08-24 14:57:36 +02002862/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002863static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002864read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002865 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002866{
Radek Krejci76512572015-08-04 09:47:08 +02002867 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002868 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 struct lyxml_elem *sub, *next;
2870 const char *value;
2871 int r;
2872 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002873 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002876 if (!anyxml) {
2877 LOGMEM;
2878 return NULL;
2879 }
Radek Krejci76512572015-08-04 09:47:08 +02002880 anyxml->nodetype = LYS_ANYXML;
2881 anyxml->prev = (struct lys_node *)anyxml;
2882 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002883
Michal Vaskoe0c59842015-09-24 13:52:20 +02002884 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2885 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 goto error;
2887 }
Radek Krejci863c2852015-06-03 15:47:11 +02002888
Radek Krejcia9544502015-08-14 08:24:29 +02002889 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002890
Radek Krejcic4283442016-04-22 09:19:27 +02002891 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002892 goto error;
2893 }
2894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002896 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2897 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002898 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002899 continue;
2900 }
2901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 if (!strcmp(sub->name, "mandatory")) {
2903 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002904 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002905 goto error;
2906 }
2907 /* just checking the flags in leaf is not sufficient, we would allow
2908 * multiple mandatory statements with the "false" value
2909 */
2910 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002912 GETVAL(value, sub, "value");
2913 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002914 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002915 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002916 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002917 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002918 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 goto error;
2920 }
2921 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002922 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002923 } else if (!strcmp(sub->name, "when")) {
2924 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002925 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002926 goto error;
2927 }
2928
2929 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002930 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002931 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002932 goto error;
2933 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002934 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935 } else if (!strcmp(sub->name, "must")) {
2936 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002937 } else if (!strcmp(sub->name, "if-feature")) {
2938 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002940 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002941 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 }
2944 }
Radek Krejci863c2852015-06-03 15:47:11 +02002945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 /* middle part - process nodes with cardinality of 0..n */
2947 if (c_must) {
2948 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002949 if (!anyxml->must) {
2950 LOGMEM;
2951 goto error;
2952 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002953 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002954 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002955 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
2956 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002957 LOGMEM;
2958 goto error;
2959 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002960 }
Radek Krejci863c2852015-06-03 15:47:11 +02002961
Radek Krejci73adb602015-07-02 18:07:40 +02002962 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002964 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
2965 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 if (r) {
2967 goto error;
2968 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002969 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002970 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
2971 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002972 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002973 goto error;
2974 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002976 }
Radek Krejci863c2852015-06-03 15:47:11 +02002977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002979
2980error:
2981
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002982 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02002983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002984 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002985}
2986
Michal Vasko0d343d12015-08-24 14:57:36 +02002987/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002988static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002989read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002990 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002991{
Radek Krejci76512572015-08-04 09:47:08 +02002992 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002993 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 struct lyxml_elem *sub, *next;
2995 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01002996 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002997 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003000 if (!leaf) {
3001 LOGMEM;
3002 return NULL;
3003 }
Radek Krejci76512572015-08-04 09:47:08 +02003004 leaf->nodetype = LYS_LEAF;
3005 leaf->prev = (struct lys_node *)leaf;
3006 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003007
Michal Vaskoe0c59842015-09-24 13:52:20 +02003008 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3009 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 goto error;
3011 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003012
Radek Krejcia9544502015-08-14 08:24:29 +02003013 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003014
Radek Krejcic4283442016-04-22 09:19:27 +02003015 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003016 goto error;
3017 }
3018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003020 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3021 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003022 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003023 continue;
3024 }
3025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003026 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003027 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003028 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 goto error;
3030 }
Michal Vasko88c29542015-11-27 14:57:53 +01003031 /* HACK for unres */
3032 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003033 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejci08a11052016-06-13 15:14:30 +02003034 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003035 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003036 goto error;
3037 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003038 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 } else if (!strcmp(sub->name, "default")) {
3040 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003041 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 goto error;
3043 }
3044 GETVAL(value, sub, "value");
3045 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3046 } else if (!strcmp(sub->name, "units")) {
3047 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003048 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 goto error;
3050 }
3051 GETVAL(value, sub, "name");
3052 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3053 } else if (!strcmp(sub->name, "mandatory")) {
3054 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003055 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003056 goto error;
3057 }
3058 /* just checking the flags in leaf is not sufficient, we would allow
3059 * multiple mandatory statements with the "false" value
3060 */
3061 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 GETVAL(value, sub, "value");
3064 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003065 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003066 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003067 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003068 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003069 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 goto error;
3071 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003072 } else if (!strcmp(sub->name, "when")) {
3073 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003074 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003075 goto error;
3076 }
3077
3078 leaf->when = read_yin_when(module, sub);
3079 if (!leaf->when) {
3080 goto error;
3081 }
3082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003084 c_must++;
3085 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003086 } else if (!strcmp(sub->name, "if-feature")) {
3087 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003091 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003094
Michal Vasko88c29542015-11-27 14:57:53 +01003095 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003098 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003099 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003100 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 goto error;
3102 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003103 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003104 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003105 goto error;
3106 }
Radek Krejci841ec082016-04-05 13:05:17 +02003107 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02003108 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
Radek Krejci841ec082016-04-05 13:05:17 +02003109 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02003110 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02003111 goto error;
3112 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003113 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 /* middle part - process nodes with cardinality of 0..n */
3116 if (c_must) {
3117 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003118 if (!leaf->must) {
3119 LOGMEM;
3120 goto error;
3121 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003123 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003124 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3125 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003126 LOGMEM;
3127 goto error;
3128 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003129 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003130
Radek Krejci73adb602015-07-02 18:07:40 +02003131 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003133 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3134 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 if (r) {
3136 goto error;
3137 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003138 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003139 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3140 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003141 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003142 goto error;
3143 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003144 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003147 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003148
3149error:
3150
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003151 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003154}
3155
Michal Vasko0d343d12015-08-24 14:57:36 +02003156/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003157static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003158read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003159 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003160{
Radek Krejci76512572015-08-04 09:47:08 +02003161 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003162 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003163 struct lyxml_elem *sub, *next;
3164 const char *value;
3165 char *endptr;
3166 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003167 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003168 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003172 if (!llist) {
3173 LOGMEM;
3174 return NULL;
3175 }
Radek Krejci76512572015-08-04 09:47:08 +02003176 llist->nodetype = LYS_LEAFLIST;
3177 llist->prev = (struct lys_node *)llist;
3178 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003179
Michal Vaskoe0c59842015-09-24 13:52:20 +02003180 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3181 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 goto error;
3183 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003184
Radek Krejcia9544502015-08-14 08:24:29 +02003185 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003186
Radek Krejcic4283442016-04-22 09:19:27 +02003187 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003188 goto error;
3189 }
3190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003192 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3193 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003194 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003195 continue;
3196 }
3197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003199 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 goto error;
3202 }
Michal Vasko88c29542015-11-27 14:57:53 +01003203 /* HACK for unres */
3204 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003205 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejci08a11052016-06-13 15:14:30 +02003206 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval)) {
Michal Vasko88c29542015-11-27 14:57:53 +01003207 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 goto error;
3209 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003210 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003211 } else if (!strcmp(sub->name, "units")) {
3212 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003213 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003214 goto error;
3215 }
3216 GETVAL(value, sub, "name");
3217 llist->units = lydict_insert(module->ctx, value, strlen(value));
3218 } else if (!strcmp(sub->name, "ordered-by")) {
3219 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003220 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 goto error;
3222 }
3223 /* just checking the flags in llist is not sufficient, we would
3224 * allow multiple ordered-by statements with the "system" value
3225 */
3226 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003227
Radek Krejci1574a8d2015-08-03 14:16:52 +02003228 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3230 * state data
3231 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003232 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 continue;
3234 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003236 GETVAL(value, sub, "value");
3237 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003238 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003240 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003242 } /* else system is the default value, so we can ignore it */
3243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003244 } else if (!strcmp(sub->name, "must")) {
3245 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003246 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003247 } else if (!strcmp(sub->name, "if-feature")) {
3248 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 } else if (!strcmp(sub->name, "min-elements")) {
3252 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003253 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 goto error;
3255 }
3256 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 GETVAL(value, sub, "value");
3259 while (isspace(value[0])) {
3260 value++;
3261 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 /* convert it to uint32_t */
3264 errno = 0;
3265 endptr = NULL;
3266 val = strtoul(value, &endptr, 10);
3267 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003268 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 goto error;
3270 }
3271 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003272 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003273 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3274 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003275 goto error;
3276 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 } else if (!strcmp(sub->name, "max-elements")) {
3278 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003279 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 goto error;
3281 }
3282 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 GETVAL(value, sub, "value");
3285 while (isspace(value[0])) {
3286 value++;
3287 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003288
Radek Krejci0d7b2472016-02-12 11:11:03 +01003289 if (!strcmp(value, "unbounded")) {
3290 llist->max = 0;
3291 } else {
3292 /* convert it to uint32_t */
3293 errno = 0;
3294 endptr = NULL;
3295 val = strtoul(value, &endptr, 10);
3296 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003297 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003298 goto error;
3299 }
3300 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003301 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003302 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3303 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003304 goto error;
3305 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003307 } else if (!strcmp(sub->name, "when")) {
3308 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003309 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003310 goto error;
3311 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003312
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003313 llist->when = read_yin_when(module, sub);
3314 if (!llist->when) {
3315 goto error;
3316 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003318 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003321
Michal Vasko88c29542015-11-27 14:57:53 +01003322 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003326 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003327 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 goto error;
3329 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 /* middle part - process nodes with cardinality of 0..n */
3332 if (c_must) {
3333 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003334 if (!llist->must) {
3335 LOGMEM;
3336 goto error;
3337 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003339 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003340 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3341 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003342 LOGMEM;
3343 goto error;
3344 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003345 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003346
Radek Krejci73adb602015-07-02 18:07:40 +02003347 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003349 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3350 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003351 if (r) {
3352 goto error;
3353 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003354 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003355 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3356 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003357 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003358 goto error;
3359 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003364
3365error:
3366
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003367 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003370}
3371
Michal Vasko0d343d12015-08-24 14:57:36 +02003372/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003373static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003374read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3375 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003376{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003377 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003378 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003380 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003381 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003383 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 char *auxs;
3385 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 /* init */
3388 memset(&root, 0, sizeof root);
3389 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003392 if (!list) {
3393 LOGMEM;
3394 return NULL;
3395 }
Radek Krejci76512572015-08-04 09:47:08 +02003396 list->nodetype = LYS_LIST;
3397 list->prev = (struct lys_node *)list;
3398 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003399
Michal Vaskoe0c59842015-09-24 13:52:20 +02003400 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3401 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003402 goto error;
3403 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003404
Radek Krejcia9544502015-08-14 08:24:29 +02003405 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 /* process list's specific children */
3408 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003409 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3410 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003411 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003412 continue;
3413 }
3414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 /* data statements */
3416 if (!strcmp(sub->name, "container") ||
3417 !strcmp(sub->name, "leaf-list") ||
3418 !strcmp(sub->name, "leaf") ||
3419 !strcmp(sub->name, "list") ||
3420 !strcmp(sub->name, "choice") ||
3421 !strcmp(sub->name, "uses") ||
3422 !strcmp(sub->name, "grouping") ||
3423 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003424 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003425 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 /* array counters */
3428 } else if (!strcmp(sub->name, "key")) {
3429 /* check cardinality 0..1 */
3430 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003431 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 goto error;
3433 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 /* count the number of keys */
3436 GETVAL(value, sub, "value");
3437 key_str = value;
3438 while ((value = strpbrk(value, " \t\n"))) {
3439 list->keys_size++;
3440 while (isspace(*value)) {
3441 value++;
3442 }
3443 }
3444 list->keys_size++;
3445 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003446 if (!list->keys) {
3447 LOGMEM;
3448 goto error;
3449 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 } else if (!strcmp(sub->name, "unique")) {
3451 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003452 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003453 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 } else if (!strcmp(sub->name, "typedef")) {
3455 c_tpdf++;
3456 } else if (!strcmp(sub->name, "must")) {
3457 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003458 } else if (!strcmp(sub->name, "if-feature")) {
3459 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 /* optional stetments */
3462 } else if (!strcmp(sub->name, "ordered-by")) {
3463 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003464 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 goto error;
3466 }
3467 /* just checking the flags in llist is not sufficient, we would
3468 * allow multiple ordered-by statements with the "system" value
3469 */
3470 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003471
Radek Krejci1574a8d2015-08-03 14:16:52 +02003472 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3474 * state data
3475 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003476 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003477 continue;
3478 }
Radek Krejci345ad742015-06-03 11:04:18 +02003479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 GETVAL(value, sub, "value");
3481 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003482 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003484 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 goto error;
3486 }
3487 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003488 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 } else if (!strcmp(sub->name, "min-elements")) {
3490 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003491 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 goto error;
3493 }
3494 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 GETVAL(value, sub, "value");
3497 while (isspace(value[0])) {
3498 value++;
3499 }
Radek Krejci345ad742015-06-03 11:04:18 +02003500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 /* convert it to uint32_t */
3502 errno = 0;
3503 auxs = NULL;
3504 val = strtoul(value, &auxs, 10);
3505 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003506 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 goto error;
3508 }
3509 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003510 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003511 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3512 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003513 lyxml_free(module->ctx, sub);
3514 goto error;
3515 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003516 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 } else if (!strcmp(sub->name, "max-elements")) {
3518 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003519 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 goto error;
3521 }
3522 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003524 GETVAL(value, sub, "value");
3525 while (isspace(value[0])) {
3526 value++;
3527 }
Radek Krejci345ad742015-06-03 11:04:18 +02003528
Radek Krejci0d7b2472016-02-12 11:11:03 +01003529 if (!strcmp(value, "unbounded")) {
3530 list->max = 0;;
3531 } else {
3532 /* convert it to uint32_t */
3533 errno = 0;
3534 auxs = NULL;
3535 val = strtoul(value, &auxs, 10);
3536 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003537 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003538 goto error;
3539 }
3540 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003541 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003542 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3543 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003544 goto error;
3545 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003547 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003548 } else if (!strcmp(sub->name, "when")) {
3549 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003550 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003551 goto error;
3552 }
3553
3554 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003555 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003556 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003557 goto error;
3558 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003559 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003560 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003561 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003562 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003563 }
3564 }
Radek Krejci345ad742015-06-03 11:04:18 +02003565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003567 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003568 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003569 goto error;
3570 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3573 if (c_tpdf) {
3574 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003575 if (!list->tpdf) {
3576 LOGMEM;
3577 goto error;
3578 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003580 if (c_must) {
3581 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003582 if (!list->must) {
3583 LOGMEM;
3584 goto error;
3585 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003586 }
3587 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003588 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
3589 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003590 LOGMEM;
3591 goto error;
3592 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003593 }
Radek Krejci73adb602015-07-02 18:07:40 +02003594 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003596 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3597 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003598 if (r) {
3599 goto error;
3600 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003601 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003602 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
3603 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003604 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003605 goto error;
3606 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003607 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003608 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3609 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003610 if (r) {
3611 goto error;
3612 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 }
3614 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003615
Radek Krejcic4283442016-04-22 09:19:27 +02003616 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003617 goto error;
3618 }
3619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003620 /* last part - process data nodes */
3621 LY_TREE_FOR_SAFE(root.child, next, sub) {
3622 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003623 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003625 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003627 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003629 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003630 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003631 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003633 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003634 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003635 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003637 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003638 } else {
3639 LOGINT;
3640 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003641 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003642 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 goto error;
3644 }
Radek Krejci73adb602015-07-02 18:07:40 +02003645
Michal Vasko345da0a2015-12-02 10:35:55 +01003646 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003648
Radek Krejci461efb92016-02-12 15:52:18 +01003649 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003650 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003651 goto error;
3652 }
3653 } /* else config false list without a key, key_str presence in case of config true is checked earlier */
Radek Krejci812b10a2015-05-28 16:48:25 +02003654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 /* process unique statements */
3656 if (c_uniq) {
3657 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003658 if (!list->unique) {
3659 LOGMEM;
3660 goto error;
3661 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003662
Radek Krejci461efb92016-02-12 15:52:18 +01003663 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3664 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3665 list->unique_size++;
3666 if (r) {
3667 goto error;
3668 }
3669
3670 lyxml_free(module->ctx, sub);
3671 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003674 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003675
3676error:
3677
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003678 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003680 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003681 }
3682 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003683 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003684 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003687}
3688
Michal Vasko0d343d12015-08-24 14:57:36 +02003689/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003690static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003691read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3692 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003693{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003695 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003696 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003697 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 const char *value;
3699 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003700 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 /* init */
3703 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003706 if (!cont) {
3707 LOGMEM;
3708 return NULL;
3709 }
Radek Krejci76512572015-08-04 09:47:08 +02003710 cont->nodetype = LYS_CONTAINER;
3711 cont->prev = (struct lys_node *)cont;
3712 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003713
Michal Vaskoe0c59842015-09-24 13:52:20 +02003714 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3715 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 goto error;
3717 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003718
Radek Krejcia9544502015-08-14 08:24:29 +02003719 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 /* process container's specific children */
3722 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003723 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003724 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003725 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003726 continue;
3727 }
3728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 if (!strcmp(sub->name, "presence")) {
3730 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003731 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 goto error;
3733 }
3734 GETVAL(value, sub, "value");
3735 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003736
Michal Vasko345da0a2015-12-02 10:35:55 +01003737 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003738 } else if (!strcmp(sub->name, "when")) {
3739 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003740 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003741 goto error;
3742 }
3743
3744 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003745 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003746 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003747 goto error;
3748 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003749 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 /* data statements */
3752 } else if (!strcmp(sub->name, "container") ||
3753 !strcmp(sub->name, "leaf-list") ||
3754 !strcmp(sub->name, "leaf") ||
3755 !strcmp(sub->name, "list") ||
3756 !strcmp(sub->name, "choice") ||
3757 !strcmp(sub->name, "uses") ||
3758 !strcmp(sub->name, "grouping") ||
3759 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003760 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003761 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 /* array counters */
3764 } else if (!strcmp(sub->name, "typedef")) {
3765 c_tpdf++;
3766 } else if (!strcmp(sub->name, "must")) {
3767 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003768 } else if (!strcmp(sub->name, "if-feature")) {
3769 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003771 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 }
3774 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3777 if (c_tpdf) {
3778 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003779 if (!cont->tpdf) {
3780 LOGMEM;
3781 goto error;
3782 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 }
3784 if (c_must) {
3785 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003786 if (!cont->must) {
3787 LOGMEM;
3788 goto error;
3789 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003791 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003792 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
3793 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003794 LOGMEM;
3795 goto error;
3796 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003797 }
Radek Krejci800af702015-06-02 13:46:01 +02003798
Radek Krejci73adb602015-07-02 18:07:40 +02003799 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003801 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3802 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 if (r) {
3804 goto error;
3805 }
3806 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003807 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3808 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 if (r) {
3810 goto error;
3811 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003812 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003813 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
3814 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003815 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003816 goto error;
3817 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003820
Radek Krejcic4283442016-04-22 09:19:27 +02003821 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003822 goto error;
3823 }
3824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003825 /* last part - process data nodes */
3826 LY_TREE_FOR_SAFE(root.child, next, sub) {
3827 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003828 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003830 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003832 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003833 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003834 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003838 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003842 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003844 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 goto error;
3846 }
Radek Krejci73adb602015-07-02 18:07:40 +02003847
Michal Vasko345da0a2015-12-02 10:35:55 +01003848 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003852
3853error:
3854
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003855 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003856 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003857 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003860 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003861}
3862
Michal Vasko0d343d12015-08-24 14:57:36 +02003863/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003864static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003865read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003866 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003867{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003869 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003870 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003871 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 int r;
3873 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 /* init */
3876 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003879 if (!grp) {
3880 LOGMEM;
3881 return NULL;
3882 }
Radek Krejci76512572015-08-04 09:47:08 +02003883 grp->nodetype = LYS_GROUPING;
3884 grp->prev = (struct lys_node *)grp;
3885 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003886
Michal Vasko71e1aa82015-08-12 12:17:51 +02003887 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 goto error;
3889 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003890
Radek Krejcia9544502015-08-14 08:24:29 +02003891 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3892
Radek Krejci1d82ef62015-08-07 14:44:40 +02003893 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003894 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3895 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003896 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003897 continue;
3898 }
3899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 /* data statements */
3901 if (!strcmp(sub->name, "container") ||
3902 !strcmp(sub->name, "leaf-list") ||
3903 !strcmp(sub->name, "leaf") ||
3904 !strcmp(sub->name, "list") ||
3905 !strcmp(sub->name, "choice") ||
3906 !strcmp(sub->name, "uses") ||
3907 !strcmp(sub->name, "grouping") ||
3908 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003909 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003910 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 /* array counters */
3913 } else if (!strcmp(sub->name, "typedef")) {
3914 c_tpdf++;
3915 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003916 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 goto error;
3918 }
3919 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3922 if (c_tpdf) {
3923 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003924 if (!grp->tpdf) {
3925 LOGMEM;
3926 goto error;
3927 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003929 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003930 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
3931 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02003932 if (r) {
3933 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003934 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003936
Radek Krejcic4283442016-04-22 09:19:27 +02003937 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003938 goto error;
3939 }
3940
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003941 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02003942 if (!root.child) {
3943 LOGWRN("Grouping \"%s\" without children.", retval->name);
3944 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 LY_TREE_FOR_SAFE(root.child, next, sub) {
3946 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003947 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003949 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003950 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003951 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003953 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003954 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003956 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003957 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003963 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 goto error;
3965 }
Radek Krejci73adb602015-07-02 18:07:40 +02003966
Michal Vasko345da0a2015-12-02 10:35:55 +01003967 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003970 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003971
3972error:
3973
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003974 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003976 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003979 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003980}
3981
Michal Vasko0d343d12015-08-24 14:57:36 +02003982/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003983static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003984read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3985 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003986{
Radek Krejcie0674f82015-06-15 13:58:51 +02003987 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003988 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003989 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02003990 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003991 int r;
3992 int c_tpdf = 0;
3993
Radek Krejcie0674f82015-06-15 13:58:51 +02003994 /* init */
3995 memset(&root, 0, sizeof root);
3996
Michal Vasko38d01f72015-06-15 09:41:06 +02003997 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01003998 if (!inout) {
3999 LOGMEM;
4000 return NULL;
4001 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004002 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004003
4004 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004005 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004006 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004007 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004008 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004009 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004010 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004011 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004012 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004013 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004014 }
4015
Radek Krejci76512572015-08-04 09:47:08 +02004016 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004017
Radek Krejci6a113852015-07-03 16:04:20 +02004018 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004019 goto error;
4020 }
4021
Radek Krejcia9544502015-08-14 08:24:29 +02004022 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4023
Michal Vasko38d01f72015-06-15 09:41:06 +02004024 /* data statements */
4025 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004026 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4027 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004028 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004029 continue;
4030 }
4031
Michal Vasko38d01f72015-06-15 09:41:06 +02004032 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 !strcmp(sub->name, "leaf-list") ||
4034 !strcmp(sub->name, "leaf") ||
4035 !strcmp(sub->name, "list") ||
4036 !strcmp(sub->name, "choice") ||
4037 !strcmp(sub->name, "uses") ||
4038 !strcmp(sub->name, "grouping") ||
4039 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004040 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004041 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004044 } else if (!strcmp(sub->name, "typedef")) {
4045 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004046
Michal Vasko38d01f72015-06-15 09:41:06 +02004047 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004048 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004049 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004050 }
4051 }
4052
4053 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4054 if (c_tpdf) {
4055 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004056 if (!inout->tpdf) {
4057 LOGMEM;
4058 goto error;
4059 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004060 }
4061
Radek Krejci73adb602015-07-02 18:07:40 +02004062 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004063 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4064 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004065 if (r) {
4066 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004067 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004068 }
4069
Radek Krejcic4283442016-04-22 09:19:27 +02004070 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004071 goto error;
4072 }
4073
Michal Vasko38d01f72015-06-15 09:41:06 +02004074 /* last part - process data nodes */
4075 LY_TREE_FOR_SAFE(root.child, next, sub) {
4076 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004077 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004078 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004079 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004080 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004081 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004082 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004083 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004084 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004086 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004087 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004088 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004089 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004090 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004091 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004092 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004093 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004094 goto error;
4095 }
Radek Krejci73adb602015-07-02 18:07:40 +02004096
Michal Vasko345da0a2015-12-02 10:35:55 +01004097 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004098 }
4099
Michal Vasko38d01f72015-06-15 09:41:06 +02004100 return retval;
4101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004102error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004103
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004104 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004105 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004106 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004107 }
4108
4109 return NULL;
4110}
4111
Michal Vasko0d343d12015-08-24 14:57:36 +02004112/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004113static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004114read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4115 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004116{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004117 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004118 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004119 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004120 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004121 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004122 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004123
Michal Vaskoc6551b32015-06-16 10:51:43 +02004124 memset(&root, 0, sizeof root);
4125
Michal Vasko0ea41032015-06-16 08:53:55 +02004126 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004127 if (!notif) {
4128 LOGMEM;
4129 return NULL;
4130 }
Radek Krejci76512572015-08-04 09:47:08 +02004131 notif->nodetype = LYS_NOTIF;
4132 notif->prev = (struct lys_node *)notif;
4133 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004134
Radek Krejci6a113852015-07-03 16:04:20 +02004135 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004136 goto error;
4137 }
4138
Radek Krejcia9544502015-08-14 08:24:29 +02004139 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4140
Michal Vasko0ea41032015-06-16 08:53:55 +02004141 /* process rpc's specific children */
4142 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004143 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4144 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004145 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004146 continue;
4147 }
4148
Michal Vasko0ea41032015-06-16 08:53:55 +02004149 /* data statements */
4150 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151 !strcmp(sub->name, "leaf-list") ||
4152 !strcmp(sub->name, "leaf") ||
4153 !strcmp(sub->name, "list") ||
4154 !strcmp(sub->name, "choice") ||
4155 !strcmp(sub->name, "uses") ||
4156 !strcmp(sub->name, "grouping") ||
4157 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004158 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004159 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004162 } else if (!strcmp(sub->name, "typedef")) {
4163 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004164 } else if (!strcmp(sub->name, "if-feature")) {
4165 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004166 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004167 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004168 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004169 }
4170 }
4171
4172 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4173 if (c_tpdf) {
4174 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004175 if (!notif->tpdf) {
4176 LOGMEM;
4177 goto error;
4178 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004179 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004180 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004181 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4182 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004183 LOGMEM;
4184 goto error;
4185 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004186 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004187
Radek Krejci73adb602015-07-02 18:07:40 +02004188 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004189 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004190 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4191 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004192 if (r) {
4193 goto error;
4194 }
Radek Krejci96299152016-06-22 10:17:50 +02004195 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004196 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4197 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004198 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004199 goto error;
4200 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004201 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004202 }
4203
Radek Krejcic4283442016-04-22 09:19:27 +02004204 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004205 goto error;
4206 }
4207
Michal Vasko0ea41032015-06-16 08:53:55 +02004208 /* last part - process data nodes */
4209 LY_TREE_FOR_SAFE(root.child, next, sub) {
4210 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004211 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004212 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004213 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004214 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004215 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004216 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004217 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004218 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004219 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004220 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004221 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004222 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004223 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004224 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004225 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004226 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004227 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004228 goto error;
4229 }
Radek Krejci73adb602015-07-02 18:07:40 +02004230
Michal Vasko345da0a2015-12-02 10:35:55 +01004231 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004232 }
4233
Michal Vasko0ea41032015-06-16 08:53:55 +02004234 return retval;
4235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004236error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004237
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004238 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004239 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004240 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004241 }
4242
4243 return NULL;
4244}
4245
Michal Vasko0d343d12015-08-24 14:57:36 +02004246/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004247static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004248read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4249 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004250{
Radek Krejcie0674f82015-06-15 13:58:51 +02004251 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004252 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004253 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004254 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004255 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004256 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004257
Radek Krejcie0674f82015-06-15 13:58:51 +02004258 /* init */
4259 memset(&root, 0, sizeof root);
4260
Michal Vasko38d01f72015-06-15 09:41:06 +02004261 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004262 if (!rpc) {
4263 LOGMEM;
4264 return NULL;
4265 }
Radek Krejci76512572015-08-04 09:47:08 +02004266 rpc->nodetype = LYS_RPC;
4267 rpc->prev = (struct lys_node *)rpc;
4268 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004269
Radek Krejci6a113852015-07-03 16:04:20 +02004270 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004271 goto error;
4272 }
4273
Radek Krejcia9544502015-08-14 08:24:29 +02004274 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4275
Michal Vasko38d01f72015-06-15 09:41:06 +02004276 /* process rpc's specific children */
4277 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004278 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4279 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004280 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004281 continue;
4282 }
4283
Michal Vasko38d01f72015-06-15 09:41:06 +02004284 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004286 && (rpc->child->nodetype == LYS_INPUT
4287 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004288 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004289 goto error;
4290 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004291 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004292 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004293 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004294 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004295 && (rpc->child->nodetype == LYS_INPUT
4296 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004297 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004298 goto error;
4299 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004300 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004301 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004303 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004304 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004305 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004306 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004309 } else if (!strcmp(sub->name, "typedef")) {
4310 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004311 } else if (!strcmp(sub->name, "if-feature")) {
4312 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004313 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004314 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004315 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004316 }
4317 }
4318
4319 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4320 if (c_tpdf) {
4321 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004322 if (!rpc->tpdf) {
4323 LOGMEM;
4324 goto error;
4325 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004326 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004327 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004328 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
4329 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004330 LOGMEM;
4331 goto error;
4332 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004333 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004334
Radek Krejci73adb602015-07-02 18:07:40 +02004335 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004336 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004337 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4338 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004339 if (r) {
4340 goto error;
4341 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004342 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004343 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
4344 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004345 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004346 goto error;
4347 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004348 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004349 }
4350
Radek Krejcic4283442016-04-22 09:19:27 +02004351 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004352 goto error;
4353 }
4354
Michal Vasko38d01f72015-06-15 09:41:06 +02004355 /* last part - process data nodes */
4356 LY_TREE_FOR_SAFE(root.child, next, sub) {
4357 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004358 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004359 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004360 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004361 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004362 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004363 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004364 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004365 goto error;
4366 }
Radek Krejci73adb602015-07-02 18:07:40 +02004367
Michal Vasko345da0a2015-12-02 10:35:55 +01004368 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004369 }
4370
Michal Vasko38d01f72015-06-15 09:41:06 +02004371 return retval;
4372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004374
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004375 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004376 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004377 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004378 }
4379
4380 return NULL;
4381}
4382
Michal Vasko0d343d12015-08-24 14:57:36 +02004383/* logs directly
4384 *
Radek Krejci74705112015-06-05 10:25:44 +02004385 * resolve - referenced grouping should be bounded to the namespace (resolved)
4386 * only when uses does not appear in grouping. In a case of grouping's uses,
4387 * we just get information but we do not apply augment or refine to it.
4388 */
Radek Krejci76512572015-08-04 09:47:08 +02004389static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02004390read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004391{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004392 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004393 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004394 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004396 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004397 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004400 if (!uses) {
4401 LOGMEM;
4402 return NULL;
4403 }
Radek Krejci76512572015-08-04 09:47:08 +02004404 uses->nodetype = LYS_USES;
4405 uses->prev = (struct lys_node *)uses;
4406 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004407
Radek Krejcia9544502015-08-14 08:24:29 +02004408 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004410
Michal Vaskoe0c59842015-09-24 13:52:20 +02004411 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02004412 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 goto error;
4414 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004415
Radek Krejcia9544502015-08-14 08:24:29 +02004416 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004419 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004420 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4421 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004422 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004423 continue;
4424 }
4425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 if (!strcmp(sub->name, "refine")) {
4427 c_ref++;
4428 } else if (!strcmp(sub->name, "augment")) {
4429 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004430 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004431 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004432 } else if (!strcmp(sub->name, "when")) {
4433 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004435 goto error;
4436 }
4437
4438 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004439 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004440 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004441 goto error;
4442 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004443 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004445 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 }
4448 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004450 /* process properties with cardinality 0..n */
4451 if (c_ref) {
4452 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004453 if (!uses->refine) {
4454 LOGMEM;
4455 goto error;
4456 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004457 }
4458 if (c_aug) {
4459 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004460 if (!uses->augment) {
4461 LOGMEM;
4462 goto error;
4463 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004465 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004466 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
4467 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004468 LOGMEM;
4469 goto error;
4470 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004471 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004472
Radek Krejcic4283442016-04-22 09:19:27 +02004473 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004474 goto error;
4475 }
4476
Radek Krejcia9544502015-08-14 08:24:29 +02004477 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004478 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004479 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4480 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004481 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004482 goto error;
4483 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004484 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004485 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4486 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004487 if (r) {
4488 goto error;
4489 }
4490 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004491 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
4492 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004493 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004494 goto error;
4495 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 }
4497 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004498
Radek Krejci48464ed2016-03-17 15:44:09 +01004499 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004500 goto error;
4501 }
Radek Krejci74705112015-06-05 10:25:44 +02004502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004504
4505error:
4506
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004507 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004510}
4511
Michal Vasko0d343d12015-08-24 14:57:36 +02004512/* logs directly
4513 *
4514 * common code for yin_read_module() and yin_read_submodule()
4515 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516static int
Radek Krejcic071c542016-01-27 14:57:51 +01004517read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4518 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004519{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004521 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004522 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004523 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004524 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004526 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02004527 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01004528 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004529 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004530 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 +02004531
Radek Krejcic071c542016-01-27 14:57:51 +01004532 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004533 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 /* init */
4536 memset(&root, 0, sizeof root);
4537 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004538 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 /*
4541 * in the first run, we process elements with cardinality of 1 or 0..1 and
4542 * count elements with cardinality 0..n. Data elements (choices, containers,
4543 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4544 * need have all top-level and groupings already prepared at that time. In
4545 * the middle loop, we process other elements with carinality of 0..n since
4546 * we need to allocate arrays to store them.
4547 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004548 LY_TREE_FOR_SAFE(yin->child, next, child) {
4549 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004550 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004551 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004552 continue;
4553 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004554
Radek Krejcic071c542016-01-27 14:57:51 +01004555 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004557 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 goto error;
4559 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004560 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004562 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004563 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 goto error;
4567 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004568 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004569 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 goto error;
4571 }
4572 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004573 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004574 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4575 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004576 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 goto error;
4578 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004579 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004580 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004581 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 goto error;
4583 }
Radek Krejcif3886932015-06-04 17:36:06 +02004584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004586 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004587 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004589 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004590 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004592 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004593 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 goto error;
4595 }
4596 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004597 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 /* check here differs from a generic prefix check, since this prefix
4599 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004600 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004601 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 goto error;
4603 }
Radek Krejcic071c542016-01-27 14:57:51 +01004604 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004607 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004608
4609 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004610 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004611 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004612 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004614 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004616 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004618 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004620 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004621 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004622 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004623 lyxml_unlink_elem(ctx, child, 2);
4624 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004625
Radek Krejci1d82ef62015-08-07 14:44:40 +02004626 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004627 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004628 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004629 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004632 } else if (!strcmp(child->name, "container") ||
4633 !strcmp(child->name, "leaf-list") ||
4634 !strcmp(child->name, "leaf") ||
4635 !strcmp(child->name, "list") ||
4636 !strcmp(child->name, "choice") ||
4637 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004638 !strcmp(child->name, "anyxml") ||
4639 !strcmp(child->name, "rpc") ||
4640 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004641 lyxml_unlink_elem(ctx, child, 2);
4642 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004643
Radek Krejci1d82ef62015-08-07 14:44:40 +02004644 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004646 lyxml_unlink_elem(ctx, child, 2);
4647 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004650 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004651 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 goto error;
4654 }
Radek Krejcic071c542016-01-27 14:57:51 +01004655 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004656 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004657 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 goto error;
4659 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004660 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004661 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004662 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 goto error;
4664 }
Radek Krejcic071c542016-01-27 14:57:51 +01004665 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004666 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004667 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 goto error;
4669 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004670 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004671 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004672 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 goto error;
4674 }
Radek Krejcic071c542016-01-27 14:57:51 +01004675 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004676 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004677 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 goto error;
4679 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004681 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004682 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 goto error;
4684 }
Radek Krejcic071c542016-01-27 14:57:51 +01004685 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004686 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004687 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 goto error;
4689 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004691 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004692 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004693 goto error;
4694 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004695 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02004696 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004697 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 goto error;
4699 }
Radek Krejcic071c542016-01-27 14:57:51 +01004700 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02004701 if (!strcmp(value, "1")) {
4702 if (submodule) {
4703 if (module->version > 1) {
4704 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4705 goto error;
4706 }
4707 } else {
4708 module->version = 1;
4709 }
4710 } else {
4711 if (submodule) {
4712 if (module->version != 2) {
4713 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4714 goto error;
4715 }
4716 } else {
4717 module->version = 2;
4718 }
4719 }
4720
Michal Vasko345da0a2015-12-02 10:35:55 +01004721 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004722
Radek Krejci1d82ef62015-08-07 14:44:40 +02004723 } else if (!strcmp(child->name, "extension")) {
4724 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004725
Radek Krejci3d468122015-10-02 13:36:12 +02004726 /* we have the following supported (hardcoded) extensions: */
4727 /* ietf-netconf's get-filter-element-attributes */
4728 if (!strcmp(module->ns, LY_NSNC) &&
4729 !strcmp(value, "get-filter-element-attributes")) {
4730 LOGDBG("NETCONF filter extension found");
4731 /* NACM's default-deny-write and default-deny-all */
4732 } else if (!strcmp(module->ns, LY_NSNACM) &&
4733 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4734 LOGDBG("NACM extension found");
4735 /* other extensions are not supported, so inform about such an extension */
4736 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004737 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004738 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004741 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004743 }
4744 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004745
Radek Krejcic071c542016-01-27 14:57:51 +01004746 /* check for mandatory statements */
4747 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004748 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004749 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004750 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004752 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 goto error;
4754 }
4755 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004756 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 goto error;
4758 }
4759 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 /* allocate arrays for elements with cardinality of 0..n */
4762 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004763 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
4764 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004765 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004766 LOGMEM;
4767 goto error;
4768 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004769 /* set stop block for possible realloc */
4770 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 }
4772 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004773 trg->rev = calloc(c_rev, sizeof *trg->rev);
4774 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004775 LOGMEM;
4776 goto error;
4777 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004778 }
4779 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004780 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4781 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004782 LOGMEM;
4783 goto error;
4784 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004785 }
4786 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004787 trg->ident = calloc(c_ident, sizeof *trg->ident);
4788 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004789 LOGMEM;
4790 goto error;
4791 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004792 }
4793 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004794 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
4795 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004796 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004797 LOGMEM;
4798 goto error;
4799 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004800 /* set stop block for possible realloc */
4801 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004803 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004804 trg->augment = calloc(c_aug, sizeof *trg->augment);
4805 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004806 LOGMEM;
4807 goto error;
4808 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004809 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004810 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004811 trg->features = calloc(c_ftrs, sizeof *trg->features);
4812 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004813 LOGMEM;
4814 goto error;
4815 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004816 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004817 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004818 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4819 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004820 LOGMEM;
4821 goto error;
4822 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004823 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004824
Michal Vasko2f7925f2015-10-21 15:06:56 +02004825 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4826 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004827 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004828 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4829 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 if (r) {
4831 goto error;
4832 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004833
Radek Krejci1d82ef62015-08-07 14:44:40 +02004834 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004835 memset(&inc, 0, sizeof inc);
4836 /* 1) pass module, not trg, since we want to pass the main module
4837 * 2) we cannot pass directly the structure in the array since
4838 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004839 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004840 if (!r) {
4841 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02004842 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
4843 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004844 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 goto error;
4846 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004847
Radek Krejci1d82ef62015-08-07 14:44:40 +02004848 } else if (!strcmp(child->name, "revision")) {
4849 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004850 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 goto error;
4852 }
Radek Krejcic071c542016-01-27 14:57:51 +01004853 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004855 for (i = 0; i < trg->rev_size; i++) {
4856 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004857 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
4858 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 }
4860 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004861
Radek Krejci1d82ef62015-08-07 14:44:40 +02004862 LY_TREE_FOR(child->child, child2) {
4863 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004864 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004865 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 goto error;
4867 }
Radek Krejcic071c542016-01-27 14:57:51 +01004868 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
4869 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 goto error;
4871 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004872 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004873 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004874 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 goto error;
4876 }
Radek Krejcic071c542016-01-27 14:57:51 +01004877 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
4878 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 goto error;
4880 }
4881 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004882 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 goto error;
4884 }
4885 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01004888 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01004890 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01004891 if (!value) {
4892 LOGMEM;
4893 goto error;
4894 }
Radek Krejcic071c542016-01-27 14:57:51 +01004895 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
4896 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004898
Radek Krejci749190d2016-02-18 16:26:25 +01004899 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004900 value = trg->rev[0].dsc;
4901 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
4902 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004904
Radek Krejci749190d2016-02-18 16:26:25 +01004905 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01004906 value = trg->rev[0].ref;
4907 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
4908 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 }
4910 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004911
Radek Krejcic071c542016-01-27 14:57:51 +01004912 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004913
Radek Krejci1d82ef62015-08-07 14:44:40 +02004914 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004915 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
4916 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 if (r) {
4918 goto error;
4919 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004920
Radek Krejci1d82ef62015-08-07 14:44:40 +02004921 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004922 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
4923 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 if (r) {
4925 goto error;
4926 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004927
Radek Krejci1d82ef62015-08-07 14:44:40 +02004928 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004929 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
4930 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004931 if (r) {
4932 goto error;
4933 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004934
Radek Krejci1d82ef62015-08-07 14:44:40 +02004935 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004936 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
4937 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004938 if (r) {
4939 goto error;
4940 }
Michal Vasko53a42af2016-02-12 11:05:02 +01004941 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
4942 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004944 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004946
Radek Krejcib8f98c12016-06-24 10:30:46 +02004947 if (!submodule) {
4948 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02004949 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02004950 if (module->inc_size) {
4951 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
4952 if (!module->inc) {
4953 LOGMEM;
4954 goto error;
4955 }
4956 }
4957 if (module->imp_size) {
4958 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
4959 if (!module->imp) {
4960 LOGMEM;
4961 goto error;
4962 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004963 }
4964 }
Radek Krejcic071c542016-01-27 14:57:51 +01004965
Radek Krejcif5be10f2015-06-16 13:29:36 +02004966 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01004967 * refer to them. Submodule's data nodes are stored in the
4968 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004969 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004970 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01004971 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004972 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004973 goto error;
4974 }
Radek Krejci74705112015-06-05 10:25:44 +02004975
Michal Vasko345da0a2015-12-02 10:35:55 +01004976 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004977 }
Radek Krejci74705112015-06-05 10:25:44 +02004978
Radek Krejcif5be10f2015-06-16 13:29:36 +02004979 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004980 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004981
Radek Krejci1d82ef62015-08-07 14:44:40 +02004982 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004983 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004984 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004985 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004986 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004987 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004988 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004989 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004990 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004991 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004992 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004993 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004994 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004995 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004996 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004997 node = read_yin_rpc(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004998 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01004999 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005000 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005001 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005002 goto error;
5003 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005004
Michal Vasko345da0a2015-12-02 10:35:55 +01005005 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005007
Michal Vasko2f7925f2015-10-21 15:06:56 +02005008 /* ... and finally augments (last, so we can augment our data, for instance) */
5009 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005010 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5011 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005012
Michal Vasko2f7925f2015-10-21 15:06:56 +02005013 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005014 goto error;
5015 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005016 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005017 }
5018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005020
5021error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005022 /* cleanup */
5023 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005024 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005025 }
5026 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005027 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005029 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005030 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005031 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005033 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005034}
5035
Michal Vasko0d343d12015-08-24 14:57:36 +02005036/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005037struct lys_submodule *
5038yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005039{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005040 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005041 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005042 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005043
Michal Vasko5a721fd2016-02-16 12:16:48 +01005044 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005045
Radek Krejci722b0072016-02-01 17:09:45 +01005046 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005048 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005051 /* check root element */
5052 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005053 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005054 goto error;
5055 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005057 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005058 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005059 goto error;
5060 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005061
Michal Vasko5a721fd2016-02-16 12:16:48 +01005062 submodule = calloc(1, sizeof *submodule);
5063 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005064 LOGMEM;
5065 goto error;
5066 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005067
Michal Vasko5a721fd2016-02-16 12:16:48 +01005068 submodule->ctx = module->ctx;
5069 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5070 submodule->type = 1;
5071 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005072
Michal Vasko5a721fd2016-02-16 12:16:48 +01005073 LOGVRB("Reading submodule \"%s\".", submodule->name);
5074 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005075 goto error;
5076 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005078 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005079 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005080
Michal Vasko5a721fd2016-02-16 12:16:48 +01005081 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005082 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005083
5084error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005086 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005087 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005088
Michal Vasko5a721fd2016-02-16 12:16:48 +01005089 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005090 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005091 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005092 }
5093
Michal Vasko5a721fd2016-02-16 12:16:48 +01005094 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005095
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005096 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5097 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005098 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005099 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005100}
5101
Michal Vasko0d343d12015-08-24 14:57:36 +02005102/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005103struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005104yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005105{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005107 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005108 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005109 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005110 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005111
Radek Krejcic071c542016-01-27 14:57:51 +01005112 unres = calloc(1, sizeof *unres);
5113 if (!unres) {
5114 LOGMEM;
5115 return NULL;
5116 }
5117
Radek Krejci722b0072016-02-01 17:09:45 +01005118 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005119 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005120 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005121 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005123 /* check root element */
5124 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005125 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005126 goto error;
5127 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005129 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005130 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 goto error;
5132 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 module = calloc(1, sizeof *module);
5135 if (!module) {
5136 LOGMEM;
5137 goto error;
5138 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005140 module->ctx = ctx;
5141 module->name = lydict_insert(ctx, value, strlen(value));
5142 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005143 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005144
Michal Vasko9f258e42016-02-11 11:36:27 +01005145 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005146 if (read_sub_module(module, NULL, yin, unres)) {
5147 goto error;
5148 }
5149
5150 /* resolve rest of unres items */
5151 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005152 goto error;
5153 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005154
Radek Krejciff4874d2016-03-07 12:30:50 +01005155 if (revision) {
5156 /* check revision of the parsed model */
5157 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005158 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5159 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005160 goto error;
5161 }
5162 }
5163
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005164 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005165 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005166 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005167
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005168 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005169 if (!module->implemented) {
5170 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5171 }
Michal Vasko26055752016-05-03 11:36:31 +02005172 if (lys_module_set_implement(module)) {
5173 goto error;
5174 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005175
Michal Vasko26055752016-05-03 11:36:31 +02005176 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5177 goto error;
5178 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005179 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005180 if (!module->inc[i].submodule) {
5181 continue;
5182 }
Michal Vasko26055752016-05-03 11:36:31 +02005183 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5184 goto error;
5185 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005186 }
5187 }
5188
Michal Vasko345da0a2015-12-02 10:35:55 +01005189 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005190 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005191 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005192 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005193
5194error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005195 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005196 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005197 unres_schema_free(module, &unres);
5198
5199 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005200 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005201 return NULL;
5202 }
5203
5204 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005205
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005206 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005207 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005209}