blob: 3befe6bac366f6c487fc25b77006558b20e58841 [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
Michal Vaskoe022a562016-09-27 14:24:15 +020045#define OPT_IDENT 0x01
46#define OPT_CFG_PARSE 0x02
47#define OPT_CFG_INHERIT 0x04
48#define OPT_CFG_IGNORE 0x08
49#define OPT_MODULE 0x10
50#define OPT_NACMEXT 0x20
Radek Krejcib8048692015-08-05 13:36:34 +020051static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020052
Radek Krejcib8048692015-08-05 13:36:34 +020053static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020054 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020055static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020056 int valid_config, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020057static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020058 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020059static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020060 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020061static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020062 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020063static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020064 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020065static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020066 int valid_config, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020067static 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 +020068 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020069static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020070 int valid_config, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020071static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020072 struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020073static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020074 struct unres_schema *unres);
Michal Vaskof02e3742015-08-05 16:27:02 +020075static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020076
Michal Vasko0d343d12015-08-24 14:57:36 +020077/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020078static const char *
79read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020080{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020081 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020083 /* there should be <text> child */
84 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010085 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010086 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010087 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020088 } else if (node->child->content) {
89 len = strlen(node->child->content);
90 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010091 } else {
92 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020094}
95
Michal Vasko0d343d12015-08-24 14:57:36 +020096/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020097static int
Radek Krejci9ff0a922016-07-14 13:08:05 +020098fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_iffeature *iffeat, struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +010099{
100 int r;
101 const char *value;
102
103 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200104
105 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
106 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200107error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100108 return EXIT_FAILURE;
109 }
110
Michal Vasko97b32be2016-07-25 10:59:53 +0200111 if (!(value = transform_schema2json(parent->module, value))) {
112 return EXIT_FAILURE;
113 }
114
Radek Krejci9ff0a922016-07-14 13:08:05 +0200115 r = resolve_iffeature_compile(iffeat, value, parent, unres);
116 lydict_remove(parent->module->ctx, value);
117 if (r) {
118 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100119 }
120
Radek Krejci9ff0a922016-07-14 13:08:05 +0200121 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100122}
123
124/* logs directly */
125static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200126fill_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 +0200127{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200128 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200129 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200130 int rc;
131 int c_ftrs = 0, c_base = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200132
Michal Vasko4cfcd252015-08-03 14:31:10 +0200133 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100134 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200135
Radek Krejci76512572015-08-04 09:47:08 +0200136 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200137 return EXIT_FAILURE;
138 }
Radek Krejci04581c62015-05-22 21:24:00 +0200139
Pavol Vicand6cda452016-07-13 15:08:29 +0200140 if (dup_identities_check(ident->name, module)) {
141 return EXIT_FAILURE;
142 }
143
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200144 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200145 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
146 /* garbage */
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200147 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200148 continue;
149 }
150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200151 if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200152 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100153 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200154 return EXIT_FAILURE;
155 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200156 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100157
Radek Krejci018f1f52016-08-03 16:01:20 +0200158 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
159 c_ftrs++;
160
161 } else {
162 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
163 return EXIT_FAILURE;
164 }
165 }
166
167 if (c_base) {
168 ident->base_size = 0;
169 ident->base = calloc(c_base, sizeof *ident->base);
170 if (!ident->base) {
171 LOGMEM;
172 return EXIT_FAILURE;
173 }
174 }
175
176 if (c_ftrs) {
177 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
178 if (!ident->iffeature) {
179 LOGMEM;
180 return EXIT_FAILURE;
181 }
182 }
183
184 LY_TREE_FOR(yin->child, node) {
185 if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200186 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100187 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100188 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200189 return EXIT_FAILURE;
190 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100191
Radek Krejci48464ed2016-03-17 15:44:09 +0100192 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100193 lydict_remove(module->ctx, value);
194 return EXIT_FAILURE;
195 }
196 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200197 } else if (!strcmp(node->name, "if-feature")) {
198 rc = fill_yin_iffeature((struct lys_node *)ident, node, &ident->iffeature[ident->iffeature_size], unres);
199 ident->iffeature_size++;
200 if (rc) {
201 return EXIT_FAILURE;
202 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200203 }
204 }
205
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200206 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200207
208error:
209 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200210}
211
Michal Vasko0d343d12015-08-24 14:57:36 +0200212/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200213static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200214read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200215{
Radek Krejci73adb602015-07-02 18:07:40 +0200216 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200217 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200218
Radek Krejci73adb602015-07-02 18:07:40 +0200219 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200220 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
221 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200222 continue;
223 }
224
Radek Krejci41726f92015-06-19 13:11:05 +0200225 if (!strcmp(child->name, "description")) {
226 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100227 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200228 return EXIT_FAILURE;
229 }
230 restr->dsc = read_yin_subnode(ctx, child, "text");
231 if (!restr->dsc) {
232 return EXIT_FAILURE;
233 }
234 } else if (!strcmp(child->name, "reference")) {
235 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100236 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200237 return EXIT_FAILURE;
238 }
239 restr->ref = read_yin_subnode(ctx, child, "text");
240 if (!restr->ref) {
241 return EXIT_FAILURE;
242 }
243 } else if (!strcmp(child->name, "error-app-tag")) {
244 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100245 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200246 return EXIT_FAILURE;
247 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200248 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200249 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200250 } else if (!strcmp(child->name, "error-message")) {
251 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100252 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200253 return EXIT_FAILURE;
254 }
255 restr->emsg = read_yin_subnode(ctx, child, "value");
256 if (!restr->emsg) {
257 return EXIT_FAILURE;
258 }
259 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100260 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200261 return EXIT_FAILURE;
262 }
Radek Krejci41726f92015-06-19 13:11:05 +0200263 }
264
265 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200266
267error:
268 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200269}
270
Michal Vasko88c29542015-11-27 14:57:53 +0100271/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
272int
Radek Krejcib8048692015-08-05 13:36:34 +0200273fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci3a5501d2016-07-18 22:03:34 +0200274 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200275{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200276 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200277 struct lys_node *siter;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200278 struct lyxml_elem *next, *next2, *node, *child;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200279 struct lys_restr **restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200280 struct lys_type_bit bit, *bits_sc = NULL;
281 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200282 struct lys_type *dertype;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200283 int i, j, rc, val_set, c_ftrs;
Radek Krejcidc008d72016-02-17 13:12:14 +0100284 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200285 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200286 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200287 size_t len;
288 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200289
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200290 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100291 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200292 if (!value) {
293 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200294 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200295
296 i = parse_identifier(value);
297 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100298 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100299 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200300 goto error;
301 }
302 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100303 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200304 if (value[i]) {
305 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100306 name += i;
307 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100308 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100309 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200310 goto error;
311 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200312 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100313 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200314 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200315
Radek Krejci225376f2016-02-16 17:36:22 +0100316 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200317 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100318 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200319 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200320 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100321
322 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200323 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200324 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200325 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100326 ret = EXIT_FAILURE;
327 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200328 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200329 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200330
Radek Krejci9b6aad22016-09-20 15:55:51 +0200331 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200332 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200333 * unresolved item left inside the grouping, LY_TYPE_ERR used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200334 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
335 if (siter) {
336 if (!((struct lys_node_grp *)siter)->nacm) {
337 LOGINT;
338 goto error;
339 }
340 ((struct lys_node_grp *)siter)->nacm--;
341 } else {
342 LOGINT;
343 goto error;
344 }
345 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200347
Radek Krejcicf509982015-12-15 09:22:44 +0100348 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100349 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100350 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100351 return -1;
352 }
353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200354 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200356 /* RFC 6020 9.7.4 - bit */
357
358 /* get bit specifications, at least one must be present */
359 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200360 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
361 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100362 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200363 continue;
364 }
365
Radek Krejci994b6f62015-06-18 16:47:27 +0200366 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200367 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200368 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100369 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200370 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200371 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200372 }
373 }
Radek Krejcie663e012016-08-01 17:12:34 +0200374 dertype = &type->der->type;
375 if (!dertype->der) {
376 if (!type->info.bits.count) {
377 /* type is derived directly from buit-in bits type and bit statement is required */
378 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
379 goto error;
380 }
381 } else {
382 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
383 if (module->version < 2 && type->info.bits.count) {
384 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
385 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
386 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200387 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200388 goto error;
389 }
Radek Krejciac781922015-07-09 15:35:14 +0200390 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200391
392 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100393 if (!type->info.bits.bit) {
394 LOGMEM;
395 goto error;
396 }
Radek Krejci73adb602015-07-02 18:07:40 +0200397 p = 0;
398 i = -1;
399 LY_TREE_FOR(yin->child, next) {
400 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200401 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200402
403 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100404 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100405 goto error;
406 }
407
Radek Krejci994b6f62015-06-18 16:47:27 +0200408 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200409 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200410 type->info.bits.count = i + 1;
411 goto error;
412 }
413
Radek Krejcie663e012016-08-01 17:12:34 +0200414 if (!dertype->der) { /* directly derived type from bits built-in type */
415 /* check the name uniqueness */
416 for (j = 0; j < i; j++) {
417 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
418 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
419 type->info.bits.count = i + 1;
420 goto error;
421 }
422 }
423 } else {
424 /* restricted bits type - the name MUST be used in the base type */
425 bits_sc = dertype->info.bits.bit;
426 for (j = 0; j < dertype->info.bits.count; j++) {
427 if (ly_strequal(bits_sc[j].name, value, 1)) {
428 break;
429 }
430 }
431 if (j == dertype->info.bits.count) {
432 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200433 type->info.bits.count = i + 1;
434 goto error;
435 }
436 }
437
Radek Krejcie663e012016-08-01 17:12:34 +0200438
Radek Krejci0d70c372015-07-02 16:23:10 +0200439 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200440 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200441 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
442 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200443 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200444 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200445
Radek Krejci0d70c372015-07-02 16:23:10 +0200446 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200447 if (p_ != -1) {
448 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
449 type->info.bits.count = i + 1;
450 goto error;
451 }
452
Radek Krejci0d70c372015-07-02 16:23:10 +0200453 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200454 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200455
456 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200457 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100458 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200459 type->info.bits.count = i + 1;
460 goto error;
461 }
462 type->info.bits.bit[i].pos = (uint32_t)p_;
463
Radek Krejcie663e012016-08-01 17:12:34 +0200464 if (!dertype->der) { /* directly derived type from bits built-in type */
465 /* keep the highest enum value for automatic increment */
466 if (type->info.bits.bit[i].pos >= p) {
467 p = type->info.bits.bit[i].pos;
468 p++;
469 } else {
470 /* check that the value is unique */
471 for (j = 0; j < i; j++) {
472 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
473 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
474 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
475 type->info.bits.bit[j].name);
476 type->info.bits.count = i + 1;
477 goto error;
478 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200479 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200480 }
481 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200482
483 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
484 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200485 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100486 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200487 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200488 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200489 }
Radek Krejcie663e012016-08-01 17:12:34 +0200490
491 if (!dertype->der) { /* directly derived type from bits built-in type */
492 if (p_ == -1) {
493 /* assign value automatically */
494 if (p > UINT32_MAX) {
495 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
496 type->info.bits.count = i + 1;
497 goto error;
498 }
499 type->info.bits.bit[i].pos = (uint32_t)p;
500 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
501 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200502 }
Radek Krejcie663e012016-08-01 17:12:34 +0200503 } else { /* restricted bits type */
504 if (p_ == -1) {
505 /* automatically assign position from base type */
506 type->info.bits.bit[i].pos = bits_sc[j].pos;
507 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
508 } else {
509 /* check that the assigned position corresponds to the original
510 * position of the bit in the base type */
511 if (p_ != bits_sc[j].pos) {
512 /* p_ - assigned position in restricted bits
513 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
514 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200515 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200516 type->info.bits.count = i + 1;
517 goto error;
518 }
519 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200520 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200521
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200522 /* if-features */
523 if (c_ftrs) {
524 bits_sc = &type->info.bits.bit[i];
525 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
526 if (!bits_sc->iffeature) {
527 LOGMEM;
528 type->info.bits.count = i + 1;
529 goto error;
530 }
531
532 LY_TREE_FOR(next->child, node) {
533 if (!strcmp(node->name, "if-feature")) {
534 rc = fill_yin_iffeature((struct lys_node *)type->parent, node,
535 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
536 bits_sc->iffeature_size++;
537 if (rc) {
538 type->info.bits.count = i + 1;
539 goto error;
540 }
541 }
542 }
543 }
544
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200545 /* keep them ordered by position */
546 j = i;
547 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
548 /* switch them */
549 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
550 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
551 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
552 j--;
553 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200554 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200555 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200558 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200559 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200560 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
561 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200562 continue;
563 }
564
Radek Krejcif9401c32015-06-26 16:47:36 +0200565 if (!strcmp(node->name, "range")) {
566 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100567 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200568 goto error;
569 }
570
571 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200572 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100573 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200574 goto error;
575 }
576 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100577 if (!type->info.dec64.range) {
578 LOGMEM;
579 goto error;
580 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200581 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
582
583 /* get possible substatements */
584 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
585 goto error;
586 }
587 } else if (!strcmp(node->name, "fraction-digits")) {
588 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100589 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200590 goto error;
591 }
592 GETVAL(value, node, "value");
593 v = strtol(value, NULL, 10);
594
595 /* range check */
596 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100597 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200598 goto error;
599 }
600 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200601 type->info.dec64.div = 10;
602 for (i = 1; i < v; i++) {
603 type->info.dec64.div *= 10;
604 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200605 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100606 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200607 goto error;
608 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200609 }
610
611 /* mandatory sub-statement(s) check */
612 if (!type->info.dec64.dig && !type->der->type.der) {
613 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100614 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200615 goto error;
616 }
Radek Krejci7511f402015-07-10 09:56:30 +0200617 if (type->info.dec64.dig && type->der->type.der) {
618 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100619 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200620 goto error;
621 }
Radek Krejcib51d5932016-09-08 14:02:52 +0200622
623 /* copy fraction-digits specification from parent type for easier internal use */
624 if (type->der->type.der) {
625 type->info.dec64.dig = type->der->type.info.dec64.dig;
626 type->info.dec64.div = type->der->type.info.dec64.div;
627 }
628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200631 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200632 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200633
Radek Krejci994b6f62015-06-18 16:47:27 +0200634 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200636 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
637 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100638 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200639 continue;
640 }
641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200643 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200644 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100645 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200646 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200647 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200648 }
649 }
Radek Krejcie663e012016-08-01 17:12:34 +0200650 dertype = &type->der->type;
651 if (!dertype->der) {
652 if (!type->info.enums.count) {
653 /* type is derived directly from buit-in enumeartion type and enum statement is required */
654 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
655 goto error;
656 }
657 } else {
658 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
659 if (module->version < 2 && type->info.enums.count) {
660 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
661 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
662 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200663 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200664 goto error;
665 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200666 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200667
Radek Krejci1574a8d2015-08-03 14:16:52 +0200668 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100669 if (!type->info.enums.enm) {
670 LOGMEM;
671 goto error;
672 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200673
Radek Krejcie663e012016-08-01 17:12:34 +0200674 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200675 i = -1;
676 LY_TREE_FOR(yin->child, next) {
677 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200678 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200679
680 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100681 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100682 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
683 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100684 goto error;
685 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200686 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200687 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 type->info.enums.count = i + 1;
689 goto error;
690 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200692 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200693 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100695 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200696 type->info.enums.count = i + 1;
697 goto error;
698 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200699
Radek Krejcie663e012016-08-01 17:12:34 +0200700 if (!dertype->der) { /* directly derived type from enumeration built-in type */
701 /* check the name uniqueness */
702 for (j = 0; j < i; j++) {
703 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
704 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
705 type->info.enums.count = i + 1;
706 goto error;
707 }
708 }
709 } else {
710 /* restricted enumeration type - the name MUST be used in the base type */
711 enms_sc = dertype->info.enums.enm;
712 for (j = 0; j < dertype->info.enums.count; j++) {
713 if (ly_strequal(enms_sc[j].name, value, 1)) {
714 break;
715 }
716 }
717 if (j == dertype->info.enums.count) {
718 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200719 type->info.enums.count = i + 1;
720 goto error;
721 }
722 }
Radek Krejci04581c62015-05-22 21:24:00 +0200723
Radek Krejcie663e012016-08-01 17:12:34 +0200724 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200725 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200726 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
727 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200728 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200730
Radek Krejci0d70c372015-07-02 16:23:10 +0200731 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200732 if (val_set) {
733 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
734 type->info.enums.count = i + 1;
735 goto error;
736 }
737
Radek Krejci0d70c372015-07-02 16:23:10 +0200738 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200739 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200740
741 /* range check */
742 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100743 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200744 type->info.enums.count = i + 1;
745 goto error;
746 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200747 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200748
Radek Krejcie663e012016-08-01 17:12:34 +0200749 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200750 if (!i) {
751 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200752 v = type->info.enums.enm[i].value;
753 v++;
754 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200755 /* keep the highest enum value for automatic increment */
756 if (type->info.enums.enm[i].value >= v) {
757 v = type->info.enums.enm[i].value;
758 v++;
759 } else {
760 /* check that the value is unique */
761 for (j = 0; j < i; j++) {
762 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
763 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
764 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
765 type->info.enums.enm[j].name);
766 type->info.enums.count = i + 1;
767 goto error;
768 }
Radek Krejcie663e012016-08-01 17:12:34 +0200769 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200770 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200771 }
772 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200773 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200774
775 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
776 c_ftrs++;
777
Radek Krejci0d70c372015-07-02 16:23:10 +0200778 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100779 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200780 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200782 }
Radek Krejcie663e012016-08-01 17:12:34 +0200783
784 if (!dertype->der) { /* directly derived type from enumeration */
785 if (!val_set) {
786 /* assign value automatically */
787 if (v > INT32_MAX) {
788 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
789 type->info.enums.count = i + 1;
790 goto error;
791 }
792 type->info.enums.enm[i].value = v;
793 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
794 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200795 }
Radek Krejcie663e012016-08-01 17:12:34 +0200796 } else { /* restricted enum type */
797 if (!val_set) {
798 /* automatically assign value from base type */
799 type->info.enums.enm[i].value = enms_sc[j].value;
800 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
801 } else {
802 /* check that the assigned value corresponds to the original
803 * value of the enum in the base type */
804 if (v_ != enms_sc[j].value) {
805 /* v_ - assigned value in restricted enum
806 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
807 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +0200808 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +0200809 type->info.enums.count = i + 1;
810 goto error;
811 }
812 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200813 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200814
815 /* if-features */
816 if (c_ftrs) {
817 enms_sc = &type->info.enums.enm[i];
818 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
819 if (!enms_sc->iffeature) {
820 LOGMEM;
821 type->info.enums.count = i + 1;
822 goto error;
823 }
824
825 LY_TREE_FOR(next->child, node) {
826 if (!strcmp(node->name, "if-feature")) {
827 rc = fill_yin_iffeature((struct lys_node *)type->parent, node,
828 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
829 enms_sc->iffeature_size++;
830 if (rc) {
831 type->info.enums.count = i + 1;
832 goto error;
833 }
834 }
835 }
836 }
837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200838 }
839 break;
840
841 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200842 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200843
Michal Vaskof2d43962016-09-02 11:10:16 +0200844 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200845 LY_TREE_FOR_SAFE(yin->child, next, node) {
846 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
847 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100848 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200849 continue;
850 }
851
Michal Vaskoe29c6622015-11-27 15:02:31 +0100852 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100853 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200854 goto error;
855 }
Michal Vaskof2d43962016-09-02 11:10:16 +0200856
857 GETVAL(value, yin->child, "name");
858 /* store in the JSON format */
859 value = transform_schema2json(module, value);
860 if (!value) {
861 goto error;
862 }
863 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
864 lydict_remove(module->ctx, value);
865
866 if (rc == -1) {
867 goto error;
868 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200869 }
870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200871 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200872 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +0200873 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +0200874 break;
875 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100876 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200877 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +0200878 } else {
879 if (type->der->type.der) {
880 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
881 goto error;
882 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100885 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 goto error;
887 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200888 break;
889
890 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200891 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200892 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200893 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
894 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200895 continue;
896 }
897
Radek Krejciaf351422015-06-19 14:49:38 +0200898 if (!strcmp(node->name, "require-instance")) {
899 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100900 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200901 goto error;
902 }
903 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200904 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200905 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200906 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200907 type->info.inst.req = -1;
908 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100909 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200910 goto error;
911 }
912 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100913 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200914 goto error;
915 }
Radek Krejciaf351422015-06-19 14:49:38 +0200916 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200918 break;
919
Radek Krejcif2860132015-06-20 12:37:20 +0200920 case LY_TYPE_BINARY:
921 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 case LY_TYPE_INT8:
923 case LY_TYPE_INT16:
924 case LY_TYPE_INT32:
925 case LY_TYPE_INT64:
926 case LY_TYPE_UINT8:
927 case LY_TYPE_UINT16:
928 case LY_TYPE_UINT32:
929 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200930 /* RFC 6020 9.2.4 - range */
931
932 /* length and range are actually the same restriction, so process
933 * them by this common code, we just need to differ the name and
934 * structure where the information will be stored
935 */
936 if (type->base == LY_TYPE_BINARY) {
937 restr = &type->info.binary.length;
938 name = "length";
939 } else {
940 restr = &type->info.num.range;
941 name = "range";
942 }
943
Radek Krejci73adb602015-07-02 18:07:40 +0200944 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200945 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
946 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200947 continue;
948 }
949
Radek Krejcif2860132015-06-20 12:37:20 +0200950 if (!strcmp(node->name, name)) {
951 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100952 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200953 goto error;
954 }
955
956 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200957 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100958 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200959 goto error;
960 }
961 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100962 if (!(*restr)) {
963 LOGMEM;
964 goto error;
965 }
Radek Krejcif2860132015-06-20 12:37:20 +0200966 (*restr)->expr = lydict_insert(module->ctx, value, 0);
967
968 /* get possible substatements */
969 if (read_restr_substmt(module->ctx, *restr, node)) {
970 goto error;
971 }
972 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100973 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200974 goto error;
975 }
Radek Krejcif2860132015-06-20 12:37:20 +0200976 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200977 break;
978
979 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200980 /* flag resolving for later use */
981 if (!tpdftype) {
982 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
983 if (siter) {
984 /* just a flag - do not resolve */
985 tpdftype = 1;
986 }
987 }
988
Radek Krejcidc4c1412015-06-19 15:39:54 +0200989 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200990 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
992 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200993 continue;
994 }
995
Michal Vasko88c29542015-11-27 14:57:53 +0100996 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200997 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100998 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200999 goto error;
1000 }
1001
1002 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001003 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001004 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001005 if (!type->info.lref.path) {
1006 goto error;
1007 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001008
1009 /* try to resolve leafref path only when this is instantiated
1010 * leaf, so it is not:
1011 * - typedef's type,
1012 * - in grouping definition,
1013 * - just instantiated in a grouping definition,
1014 * because in those cases the nodes referenced in path might not be present
1015 * and it is not a bug. */
1016 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001017 goto error;
1018 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001019 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001020 if (type->info.lref.req) {
1021 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1022 goto error;
1023 }
1024 GETVAL(value, node, "value");
1025 if (!strcmp(value, "true")) {
1026 type->info.lref.req = 1;
1027 } else if (!strcmp(value, "false")) {
1028 type->info.lref.req = -1;
1029 } else {
1030 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1031 goto error;
1032 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001033 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001034 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001035 goto error;
1036 }
Radek Krejci73adb602015-07-02 18:07:40 +02001037 }
1038
Radek Krejci742be352016-07-17 12:18:54 +02001039 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001040 if (!type->der->type.der) {
1041 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Michal Vasko01c6fd22016-05-20 11:43:05 +02001042 goto error;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001043 } else {
1044 /* copy leafref definition into the derived type */
1045 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1046 /* and resolve the path at the place we are (if not in grouping/typedef) */
1047 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1048 goto error;
1049 }
1050
1051 /* add pointer to leafref target, only on leaves (not in typedefs) */
1052 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1053 goto error;
1054 }
Michal Vasko01c6fd22016-05-20 11:43:05 +02001055 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001056 }
Radek Krejci742be352016-07-17 12:18:54 +02001057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001058 break;
1059
1060 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001061 /* RFC 6020 9.4.4 - length */
1062 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001063 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001064 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001065 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1066 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001067 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001068 continue;
1069 }
1070
Radek Krejci3733a802015-06-19 13:43:21 +02001071 if (!strcmp(node->name, "length")) {
1072 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001073 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001074 goto error;
1075 }
1076
1077 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001078 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001079 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001080 goto error;
1081 }
1082 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001083 if (!type->info.str.length) {
1084 LOGMEM;
1085 goto error;
1086 }
Radek Krejci3733a802015-06-19 13:43:21 +02001087 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1088
Radek Krejci5fbc9162015-06-19 14:11:11 +02001089 /* get possible sub-statements */
1090 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001091 goto error;
1092 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001093 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001094 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001095 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001096 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001097 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001098 goto error;
1099 }
1100 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001101 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001102 if (i) {
1103 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001104 if (!type->info.str.patterns) {
1105 LOGMEM;
1106 goto error;
1107 }
Radek Krejci73adb602015-07-02 18:07:40 +02001108 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001109 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001110 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001111 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001112 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001113 goto error;
1114 }
Michal Vasko69068852015-07-13 14:34:31 +02001115
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001116 modifier = 0x06; /* ACK */
1117 name = NULL;
1118 LY_TREE_FOR_SAFE(node->child, next2, child) {
1119 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1120 /* garbage */
1121 lyxml_free(module->ctx, child);
1122 continue;
1123 }
1124
1125 if (module->version >= 2 && !strcmp(child->name, "modifier")) {
1126 if (name) {
1127 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1128 goto error;
1129 }
1130
1131 GETVAL(name, child, "value");
1132 if (!strcmp(name, "invert-match")) {
1133 modifier = 0x15; /* NACK */
1134 } else {
1135 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1136 goto error;
1137 }
1138 lyxml_free(module->ctx, child);
1139 }
1140 }
1141
1142 len = strlen(value);
1143 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1144 buf[0] = modifier;
1145 strcpy(&buf[1], value);
1146
1147 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001148
1149 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +01001150 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +02001151 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001152 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001153 goto error;
1154 }
Radek Krejci73adb602015-07-02 18:07:40 +02001155 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001156 }
1157 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001158 break;
1159
1160 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001161 /* RFC 6020 7.4 - type */
1162 /* count number of types in union */
1163 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001164 LY_TREE_FOR_SAFE(yin->child, next, node) {
1165 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1166 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001167 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001168 continue;
1169 }
1170
Radek Krejcie4c366b2015-07-02 10:11:31 +02001171 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001172 if (type->der->type.der) {
1173 /* type can be a substatement only in "union" type, not in derived types */
1174 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1175 goto error;
1176 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001177 i++;
1178 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001179 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001180 goto error;
1181 }
1182 }
1183
Radek Krejci038d5d92016-09-12 15:07:15 +02001184 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001185 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001186 goto error;
1187 }
1188
1189 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001190 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001191 if (!type->info.uni.types) {
1192 LOGMEM;
1193 goto error;
1194 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001195 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001196 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001197 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001198 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001199 if (!rc) {
1200 type->info.uni.count++;
1201
Radek Krejci7de36cf2016-09-12 16:18:50 +02001202 if (module->version < 2) {
1203 /* union's type cannot be empty or leafref */
1204 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1205 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1206 rc = -1;
1207 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1208 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1209 rc = -1;
1210 }
Michal Vasko88c29542015-11-27 14:57:53 +01001211 }
1212 }
1213 if (rc) {
1214 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1215 for (i = 0; i < type->info.uni.count; ++i) {
1216 lys_type_free(module->ctx, &type->info.uni.types[i]);
1217 }
1218 free(type->info.uni.types);
1219 type->info.uni.types = NULL;
1220 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001221 type->der = NULL;
1222 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001223
1224 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001225 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001226 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001227 goto error;
1228 }
Michal Vasko88c29542015-11-27 14:57:53 +01001229 }
1230 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001231
Michal Vasko88c29542015-11-27 14:57:53 +01001232 case LY_TYPE_BOOL:
1233 case LY_TYPE_EMPTY:
1234 /* no sub-statement allowed */
1235 LY_TREE_FOR(yin->child, node) {
1236 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001237 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001238 goto error;
1239 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001240 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001241 break;
1242
1243 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001244 LOGINT;
1245 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001246 }
1247
1248 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001249
1250error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001251 if (type->module_name) {
1252 lydict_remove(module->ctx, type->module_name);
1253 type->module_name = NULL;
1254 }
1255 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001256}
1257
Michal Vasko0d343d12015-08-24 14:57:36 +02001258/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001259static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001260fill_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 +02001261{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001262 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001263 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +01001264 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001267 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001268 goto error;
1269 }
1270 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001273 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001274 goto error;
1275 }
Radek Krejcieac35532015-05-31 19:09:15 +02001276
Michal Vasko88c29542015-11-27 14:57:53 +01001277 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001278 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1279 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001280 continue;
1281 }
1282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001283 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001284 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001285 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286 goto error;
1287 }
Michal Vasko88c29542015-11-27 14:57:53 +01001288 /* HACK for unres */
1289 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001290 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001291 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001292 goto error;
1293 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001294 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001295 } else if (!strcmp(node->name, "default")) {
1296 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001297 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298 goto error;
1299 }
1300 GETVAL(value, node, "value");
1301 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1302 } else if (!strcmp(node->name, "units")) {
1303 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001304 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001305 goto error;
1306 }
1307 GETVAL(value, node, "name");
1308 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1309 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001310 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001311 goto error;
1312 }
1313 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001315 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001316 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001317 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001318 goto error;
1319 }
Radek Krejcieac35532015-05-31 19:09:15 +02001320
Michal Vasko478c4652016-07-21 12:55:01 +02001321 /* check default value (if not defined, there still could be some restrictions
1322 * that need to be checked against a default value from a derived type) */
1323 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
1324 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001325 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001327 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001328
1329error:
1330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001331 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001332}
1333
Michal Vasko0d343d12015-08-24 14:57:36 +02001334/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001335static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001336fill_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 +02001337{
1338 const char *value;
1339 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001340 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001341
Radek Krejcib05774c2015-06-18 13:52:59 +02001342 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001343 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001344 goto error;
1345 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001346 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001347 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001348
Radek Krejci76512572015-08-04 09:47:08 +02001349 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001350 goto error;
1351 }
1352
1353 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001354 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1355 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001356 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001357 continue;
1358 }
1359
Radek Krejci3cf9e222015-06-18 11:37:50 +02001360 if (!strcmp(child->name, "if-feature")) {
1361 c++;
1362 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001363 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001364 goto error;
1365 }
1366 }
1367
1368 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001369 f->iffeature = calloc(c, sizeof *f->iffeature);
1370 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001371 LOGMEM;
1372 goto error;
1373 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001374 }
Radek Krejci73adb602015-07-02 18:07:40 +02001375 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001376 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1377 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001378 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001379 goto error;
1380 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001381 }
1382
Radek Krejcic79c6b12016-07-26 15:11:49 +02001383 /* check for circular dependencies */
1384 if (f->iffeature_size) {
1385 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1386 goto error;
1387 }
1388 }
1389
Radek Krejci3cf9e222015-06-18 11:37:50 +02001390 return EXIT_SUCCESS;
1391
1392error:
1393
1394 return EXIT_FAILURE;
1395}
1396
Michal Vasko0d343d12015-08-24 14:57:36 +02001397/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398static int
Radek Krejcib8048692015-08-05 13:36:34 +02001399fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001400{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001401 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001404 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001405 if (!must->expr) {
1406 goto error;
1407 }
Radek Krejci800af702015-06-02 13:46:01 +02001408
Radek Krejci41726f92015-06-19 13:11:05 +02001409 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001410
Michal Vasko77dc5652016-02-15 12:32:42 +01001411error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001412 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001413}
1414
Radek Krejci581ce772015-11-10 17:22:40 +01001415static int
Michal Vasko88c29542015-11-27 14:57:53 +01001416fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1417 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001418{
1419 int i, j;
1420 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001421 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001422
1423 /* get unique value (list of leafs supposed to be unique */
1424 GETVAL(value, yin, "tag");
1425
1426 /* count the number of unique leafs in the value */
1427 vaux = value;
1428 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001429 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001430 while (isspace(*vaux)) {
1431 vaux++;
1432 }
1433 }
1434 unique->expr_size++;
1435 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001436 if (!unique->expr) {
1437 LOGMEM;
1438 goto error;
1439 }
Radek Krejci581ce772015-11-10 17:22:40 +01001440
1441 for (i = 0; i < unique->expr_size; i++) {
1442 vaux = strpbrk(value, " \t\n");
1443 if (!vaux) {
1444 /* the last token, lydict_insert() will count its size on its own */
1445 vaux = value;
1446 }
1447
1448 /* store token into unique structure */
1449 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1450
1451 /* check that the expression does not repeat */
1452 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001453 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001454 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1455 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001456 goto error;
1457 }
1458 }
1459
1460 /* try to resolve leaf */
1461 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001462 unique_info = malloc(sizeof *unique_info);
1463 unique_info->list = parent;
1464 unique_info->expr = unique->expr[i];
1465 unique_info->trg_type = &unique->trg_type;
1466 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001467 goto error;
1468 }
Radek Krejci581ce772015-11-10 17:22:40 +01001469 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001470 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001471 goto error;
1472 }
1473 }
1474
1475 /* move to next token */
1476 value = vaux;
1477 while(isspace(*value)) {
1478 value++;
1479 }
1480 }
1481
1482 return EXIT_SUCCESS;
1483
1484error:
1485 return EXIT_FAILURE;
1486}
1487
Michal Vasko0d343d12015-08-24 14:57:36 +02001488/* logs directly
1489 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001490 * type: 0 - min, 1 - max
1491 */
1492static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001493deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001494{
1495 const char *value;
1496 char *endptr;
1497 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001498 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001499
Michal Vaskof7e57d52016-03-07 11:31:09 +01001500 /* del min/max is forbidden */
1501 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001502 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001503 goto error;
1504 }
1505
Radek Krejcieb00f512015-07-01 16:44:58 +02001506 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001507 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001508 max = &((struct lys_node_leaflist *)target)->max;
1509 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001510 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001511 max = &((struct lys_node_list *)target)->max;
1512 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001514 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1515 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001516 goto error;
1517 }
1518
1519 GETVAL(value, node, "value");
1520 while (isspace(value[0])) {
1521 value++;
1522 }
1523
Radek Krejci0d7b2472016-02-12 11:11:03 +01001524 if (type && !strcmp(value, "unbounded")) {
1525 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001526 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001527 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001528 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001529 /* convert it to uint32_t */
1530 errno = 0;
1531 endptr = NULL;
1532 val = strtoul(value, &endptr, 10);
1533 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001534 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001535 goto error;
1536 }
1537 if (type) {
1538 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001539 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001540 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001541 } else {
1542 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001543 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001544 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001545 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001546 }
1547
1548 if (d->mod == LY_DEVIATE_ADD) {
1549 /* check that there is no current value */
1550 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001551 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1552 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001553 goto error;
1554 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001555 } else if (d->mod == LY_DEVIATE_RPL) {
1556 /* unfortunately, there is no way to check reliably that there
1557 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001558 }
1559
Michal Vaskof7e57d52016-03-07 11:31:09 +01001560 /* add (already checked) and replace */
1561 /* set new value specified in deviation */
1562 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001563
Pavol Vican09adcc32016-08-25 10:51:36 +02001564 /* check min-elements is smaller than max-elements */
1565 if (*max && *min > *max) {
1566 if (type) {
1567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
1568 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1569 } else {
1570 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
1571 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1572 }
1573 goto error;
1574 }
1575
Radek Krejcieb00f512015-07-01 16:44:58 +02001576 return EXIT_SUCCESS;
1577
1578error:
1579
1580 return EXIT_FAILURE;
1581}
1582
Michal Vasko0d343d12015-08-24 14:57:36 +02001583/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001584static int
Michal Vasko88c29542015-11-27 14:57:53 +01001585fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1586 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001587{
1588 const char *value, **stritem;
1589 struct lyxml_elem *next, *child, *develem;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001590 int c_dev = 0, c_must, c_uniq, c_dflt;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001591 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001592 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001593 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001594 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001595 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001596 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001597 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001598 struct lys_node_leaf *leaf = NULL;
1599 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001600 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001601 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001602 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001603 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001604 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001605 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001606 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02001607
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001608 ctx = module->ctx;
1609
Radek Krejcieb00f512015-07-01 16:44:58 +02001610 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001611 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001612 if (!dev->target_name) {
1613 goto error;
1614 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001615
1616 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001617 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1618 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001619 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001620 goto error;
1621 }
Radek Krejcic4283442016-04-22 09:19:27 +02001622 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001623 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1624 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001625 goto error;
1626 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001627
1628 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001629 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1630 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001631 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001632 continue;
1633 }
1634
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 if (!strcmp(child->name, "description")) {
1636 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001637 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 goto error;
1639 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001640 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 if (!dev->dsc) {
1642 goto error;
1643 }
1644 } else if (!strcmp(child->name, "reference")) {
1645 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001646 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 goto error;
1648 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001649 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 if (!dev->ref) {
1651 goto error;
1652 }
1653 } else if (!strcmp(child->name, "deviate")) {
1654 c_dev++;
1655
Michal Vasko345da0a2015-12-02 10:35:55 +01001656 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001657 * further processed later
1658 */
1659 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001660
Radek Krejcieb00f512015-07-01 16:44:58 +02001661 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001662 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001663 goto error;
1664 }
1665
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001666 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 }
1668
1669 if (c_dev) {
1670 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001671 if (!dev->deviate) {
1672 LOGMEM;
1673 goto error;
1674 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001675 } else {
1676 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1677 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001678 }
1679
1680 LY_TREE_FOR(yin->child, develem) {
1681 /* init */
1682 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001683 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001684 c_must = 0;
1685 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001686 c_dflt = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001687
1688 /* get deviation type */
1689 GETVAL(value, develem, "value");
1690 if (!strcmp(value, "not-supported")) {
1691 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1692 /* no property expected in this case */
1693 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001694 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001695 goto error;
1696 }
1697
Radek Krejci5b917642015-07-02 09:03:13 +02001698 /* and neither any other deviate statement is expected,
1699 * not-supported deviation must be the only deviation of the target
1700 */
1701 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001702 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1703 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001704 goto error;
1705 }
1706
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001707 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001708 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1709 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1710 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001711 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1712 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001713 goto error;
1714 }
1715 }
1716 }
Radek Krejci5b917642015-07-02 09:03:13 +02001717
Michal Vaskoff006c12016-02-17 11:15:19 +01001718 /* unlink and store the original node */
1719 lys_node_unlink(dev_target);
1720 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001721
Radek Krejci5b917642015-07-02 09:03:13 +02001722 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02001723 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02001724 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 } else if (!strcmp(value, "add")) {
1726 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1727 } else if (!strcmp(value, "replace")) {
1728 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1729 } else if (!strcmp(value, "delete")) {
1730 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1731 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001732 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001733 goto error;
1734 }
1735 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001736 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001737
Michal Vaskoff006c12016-02-17 11:15:19 +01001738 /* store a shallow copy of the original node */
1739 if (!dev->orig_node) {
1740 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001741 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01001742 /* just to be safe */
1743 if (tmp_unres.count) {
1744 LOGINT;
1745 goto error;
1746 }
1747 }
1748
Radek Krejcieb00f512015-07-01 16:44:58 +02001749 /* process deviation properties */
1750 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001751 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1752 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001753 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001754 continue;
1755 }
1756
Radek Krejcieb00f512015-07-01 16:44:58 +02001757 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001758 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001759 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001760 goto error;
1761 }
1762
1763 /* for we deviate from RFC 6020 and allow config property even it is/is not
1764 * specified in the target explicitly since config property inherits. So we expect
1765 * that config is specified in every node. But for delete, we check that the value
1766 * is the same as here in deviation
1767 */
1768 GETVAL(value, child, "value");
1769 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001770 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001772 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001773 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001774 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001775 goto error;
1776 }
1777
1778 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001779 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001780 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001781 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001782 } else { /* add and replace are the same in this case */
1783 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001784 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001785
1786 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001787 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 }
1789 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001790 c_dflt++;
1791
1792 /* check target node type */
1793 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1794 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1795 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1796 goto error;
1797 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1798 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1799 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1800 goto error;
1801 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
1802 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1803 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001804 goto error;
1805 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001806
Radek Krejcid5a5c282016-08-15 15:38:08 +02001807 /* skip lyxml_free() at the end of the loop, this node will be processed later */
1808 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02001809
Radek Krejcieb00f512015-07-01 16:44:58 +02001810 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001811 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001812 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001813 goto error;
1814 }
1815
1816 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001817 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001818 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1819 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001820 goto error;
1821 }
1822
1823 GETVAL(value, child, "value");
1824 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001825 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001826 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001827 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001828 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001829 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001830 goto error;
1831 }
1832
1833 if (d->mod == LY_DEVIATE_ADD) {
1834 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001835 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001836 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1837 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001838 goto error;
1839 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001840
Radek Krejci841ec082016-04-05 13:05:17 +02001841 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02001842 if (d->flags & LYS_MAND_TRUE) {
1843 if (dev_target->nodetype == LYS_CHOICE) {
1844 if (((struct lys_node_choice *)(dev_target))->dflt) {
1845 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1846 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1847 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
1848 goto error;
1849 }
1850 } else if (dev_target->nodetype == LYS_LEAF) {
1851 if (((struct lys_node_leaf *)(dev_target))->dflt) {
1852 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1853 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1854 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
1855 goto error;
1856 }
1857 }
Radek Krejci841ec082016-04-05 13:05:17 +02001858 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001859
Michal Vasko21be1b32016-03-07 12:31:34 +01001860 dev_target->flags |= d->flags & LYS_MAND_MASK;
1861 } else if (d->mod == LY_DEVIATE_RPL) {
1862 /* check that there was a value before */
1863 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001864 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1865 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001866 goto error;
1867 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001868
Michal Vasko21be1b32016-03-07 12:31:34 +01001869 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001870 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001871 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001872 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001873 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001874 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001875 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001876
1877 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
1878 for (parent = dev_target->parent;
1879 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1880 parent = parent->parent) {
1881 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1882 /* stop also on presence containers */
1883 break;
1884 }
1885 }
1886 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1887 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1888 if (lyp_check_mandatory_choice(parent)) {
1889 goto error;
1890 }
1891 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001892 } else if (!strcmp(child->name, "min-elements")) {
1893 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001894 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001895 goto error;
1896 }
1897 f_min = 1;
1898
Michal Vasko60f4b452016-02-12 11:02:55 +01001899 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001900 goto error;
1901 }
1902 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001903 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001904 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001905 goto error;
1906 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001907 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001908
Michal Vasko60f4b452016-02-12 11:02:55 +01001909 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 goto error;
1911 }
1912 } else if (!strcmp(child->name, "must")) {
1913 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001914 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001915 continue;
1916 } else if (!strcmp(child->name, "type")) {
1917 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001918 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001919 goto error;
1920 }
1921
Michal Vaskof7e57d52016-03-07 11:31:09 +01001922 /* add, del type is forbidden */
1923 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001924 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001925 goto error;
1926 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001927 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001928 goto error;
1929 }
1930
Radek Krejcieb00f512015-07-01 16:44:58 +02001931 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001932 if (dev_target->nodetype == LYS_LEAF) {
1933 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001934 if (((struct lys_node_leaf *)dev_target)->dflt) {
1935 ly_set_add(dflt_check, dev_target, 0);
1936 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001937 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1938 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001939 if (((struct lys_node_leaflist *)dev_target)->dflt) {
1940 ly_set_add(dflt_check, dev_target, 0);
1941 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001942 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001943 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1944 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001945 goto error;
1946 }
1947
Radek Krejcieb00f512015-07-01 16:44:58 +02001948 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001949 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001950 /* HACK for unres */
1951 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001952 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001953 goto error;
1954 }
1955 d->type = t;
1956 } else if (!strcmp(child->name, "unique")) {
1957 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001958 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001959 continue;
1960 } else if (!strcmp(child->name, "units")) {
1961 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001962 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001963 goto error;
1964 }
1965
1966 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001967 if (dev_target->nodetype == LYS_LEAFLIST) {
1968 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1969 } else if (dev_target->nodetype == LYS_LEAF) {
1970 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001971 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001972 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1973 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001974 goto error;
1975 }
1976
1977 /* get units value */
1978 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001979 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001980
1981 /* apply to target */
1982 if (d->mod == LY_DEVIATE_ADD) {
1983 /* check that there is no current value */
1984 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001985 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1986 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001987 goto error;
1988 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001989
Michal Vasko21be1b32016-03-07 12:31:34 +01001990 *stritem = lydict_insert(ctx, value, 0);
1991 } else if (d->mod == LY_DEVIATE_RPL) {
1992 /* check that there was a value before */
1993 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001994 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1995 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001996 goto error;
1997 }
1998
1999 lydict_remove(ctx, *stritem);
2000 *stritem = lydict_insert(ctx, value, 0);
2001 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002002 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002003 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002004 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2005 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002006 goto error;
2007 }
2008 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002009 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002010 }
2011 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002012 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002013 goto error;
2014 }
2015
Michal Vasko88c29542015-11-27 14:57:53 +01002016 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002017 }
2018
2019 if (c_must) {
2020 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002021 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002022 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002023 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2024 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002025 break;
Radek Krejci76512572015-08-04 09:47:08 +02002026 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002027 trg_must = &((struct lys_node_container *)dev_target)->must;
2028 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002029 break;
Radek Krejci76512572015-08-04 09:47:08 +02002030 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002031 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2032 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002033 break;
Radek Krejci76512572015-08-04 09:47:08 +02002034 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002035 trg_must = &((struct lys_node_list *)dev_target)->must;
2036 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002037 break;
Radek Krejci76512572015-08-04 09:47:08 +02002038 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002039 case LYS_ANYDATA:
2040 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2041 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002042 break;
2043 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002044 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2045 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002046 goto error;
2047 }
2048
Michal Vasko508a50d2016-09-07 14:50:33 +02002049 dev_target->flags &= ~LYS_XPATH_DEP;
2050
Radek Krejcieb00f512015-07-01 16:44:58 +02002051 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002052 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002053 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002054 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002055 } else if (d->mod == LY_DEVIATE_ADD) {
2056 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002057 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002058 if (!d->must) {
2059 LOGMEM;
2060 goto error;
2061 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002062 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002063 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002064 d->must_size = c_must;
2065 } else { /* LY_DEVIATE_DEL */
2066 d->must = calloc(c_must, sizeof *d->must);
2067 }
Michal Vasko253035f2015-12-17 16:58:13 +01002068 if (!d->must) {
2069 LOGMEM;
2070 goto error;
2071 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002072 }
2073 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002074 /* replace unique is forbidden */
2075 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002076 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002077 goto error;
2078 }
2079
Radek Krejcieb00f512015-07-01 16:44:58 +02002080 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002081 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002082 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2083 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002084 goto error;
2085 }
2086
Michal Vasko60f4b452016-02-12 11:02:55 +01002087 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002088 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002089 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002090 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002091 list->unique = d->unique;
2092 d->unique = &list->unique[list->unique_size];
2093 d->unique_size = c_uniq;
2094 } else { /* LY_DEVIATE_DEL */
2095 d->unique = calloc(c_uniq, sizeof *d->unique);
2096 }
Michal Vasko253035f2015-12-17 16:58:13 +01002097 if (!d->unique) {
2098 LOGMEM;
2099 goto error;
2100 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002101 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002102 if (c_dflt) {
2103 if (d->mod == LY_DEVIATE_ADD) {
2104 /* check that there is no current value */
2105 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2106 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2107 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2108 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2109 goto error;
2110 }
2111
2112 /* check collision with mandatory/min-elements */
2113 if ((dev_target->flags & LYS_MAND_TRUE) ||
2114 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2115 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2116 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2117 "Adding the \"default\" statement is forbidden on %s statement.",
2118 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2119 goto error;
2120 }
2121 } else if (d->mod == LY_DEVIATE_RPL) {
2122 /* check that there was a value before */
2123 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2124 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2125 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2126 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2127 goto error;
2128 }
2129 }
2130
2131 if (dev_target->nodetype == LYS_LEAFLIST) {
2132 /* reallocate default list in the target */
2133 llist = (struct lys_node_leaflist *)dev_target;
2134 if (d->mod == LY_DEVIATE_ADD) {
2135 /* reallocate (enlarge) the unique array of the target */
2136 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2137 } else if (d->mod == LY_DEVIATE_RPL) {
2138 /* reallocate (replace) the unique array of the target */
2139 for (i = 0; i < llist->dflt_size; i++) {
2140 lydict_remove(llist->module->ctx, llist->dflt[i]);
2141 }
2142 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2143 llist->dflt_size = 0;
2144 }
2145 }
2146 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2147 if (!d->dflt) {
2148 LOGMEM;
2149 goto error;
2150 }
2151 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002152
2153 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002154 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002155 if (!strcmp(child->name, "must")) {
2156 if (d->mod == LY_DEVIATE_DEL) {
2157 if (fill_yin_must(module, child, &d->must[d->must_size])) {
2158 goto error;
2159 }
2160
2161 /* find must to delete, we are ok with just matching conditions */
2162 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002163 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002164 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002165 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002166 /* ... and maintain the array */
2167 (*trg_must_size)--;
2168 if (i != *trg_must_size) {
2169 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2170 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2171 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2172 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2173 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2174 }
2175 if (!(*trg_must_size)) {
2176 free(*trg_must);
2177 *trg_must = NULL;
2178 } else {
2179 (*trg_must)[*trg_must_size].expr = NULL;
2180 (*trg_must)[*trg_must_size].dsc = NULL;
2181 (*trg_must)[*trg_must_size].ref = NULL;
2182 (*trg_must)[*trg_must_size].eapptag = NULL;
2183 (*trg_must)[*trg_must_size].emsg = NULL;
2184 }
2185
2186 i = -1; /* set match flag */
2187 break;
2188 }
2189 }
2190 d->must_size++;
2191 if (i != -1) {
2192 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002193 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002194 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002195 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002196 goto error;
2197 }
2198 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002199 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2200 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002201 goto error;
2202 }
2203 (*trg_must_size)++;
2204 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002205
2206 /* check XPath dependencies again */
2207 if (*trg_must_size && unres_schema_add_node(dev_target->module, unres, dev_target, UNRES_XPATH, NULL)) {
2208 goto error;
2209 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002210 } else if (!strcmp(child->name, "unique")) {
2211 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002212 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002213 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002214 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002215 goto error;
2216 }
2217
2218 /* find unique structures to delete */
2219 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002220 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002221 continue;
2222 }
2223
Radek Krejci581ce772015-11-10 17:22:40 +01002224 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002225 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002226 break;
2227 }
2228 }
2229
Radek Krejci581ce772015-11-10 17:22:40 +01002230 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002231 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002232 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002233 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002234 }
2235 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 /* ... and maintain the array */
2237 list->unique_size--;
2238 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002239 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2240 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002241 }
2242
2243 if (!list->unique_size) {
2244 free(list->unique);
2245 list->unique = NULL;
2246 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002247 list->unique[list->unique_size].expr_size = 0;
2248 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002249 }
2250
2251 i = -1; /* set match flag */
2252 break;
2253 }
2254 }
2255
2256 d->unique_size++;
2257 if (i != -1) {
2258 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002259 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2260 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002261 goto error;
2262 }
2263 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002264 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002265 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002266 list->unique_size++;
2267 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002268 goto error;
2269 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002270 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002271 } else if (!strcmp(child->name, "default")) {
2272 GETVAL(value, child, "value");
2273 u = strlen(value);
2274 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2275
2276 if (dev_target->nodetype == LYS_CHOICE) {
2277 choice = (struct lys_node_choice *)dev_target;
2278 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2279 if (rc || !node) {
2280 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2281 goto error;
2282 }
2283 if (d->mod == LY_DEVIATE_DEL) {
2284 if (!choice->dflt || (choice->dflt != node)) {
2285 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2286 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2287 goto error;
2288 }
2289 } else { /* add or replace */
2290 choice->dflt = node;
2291 if (!choice->dflt) {
2292 /* default branch not found */
2293 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2294 goto error;
2295 }
2296 }
2297 } else if (dev_target->nodetype == LYS_LEAF) {
2298 leaf = (struct lys_node_leaf *)dev_target;
2299 if (d->mod == LY_DEVIATE_DEL) {
2300 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2301 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2302 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2303 goto error;
2304 }
2305 /* remove value */
2306 lydict_remove(ctx, leaf->dflt);
2307 leaf->dflt = NULL;
2308 } else { /* add (already checked) and replace */
2309 /* remove value */
2310 lydict_remove(ctx, leaf->dflt);
2311
2312 /* set new value */
2313 leaf->dflt = lydict_insert(ctx, value, u);
2314
2315 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2316 ly_set_add(dflt_check, dev_target, 0);
2317 }
2318 } else { /* LYS_LEAFLIST */
2319 llist = (struct lys_node_leaflist *)dev_target;
2320 if (d->mod == LY_DEVIATE_DEL) {
2321 /* find and remove the value in target list */
2322 for (i = 0; i < llist->dflt_size; i++) {
2323 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2324 /* match, remove the value */
2325 lydict_remove(llist->module->ctx, llist->dflt[i]);
2326 llist->dflt[i] = NULL;
2327 break;
2328 }
2329 }
2330 if (i == llist->dflt_size) {
2331 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2332 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2333 goto error;
2334 }
2335 } else {
2336 /* add or replace, anyway we place items into the deviate's list
2337 which propagates to the target */
2338 /* we just want to check that the value isn't already in the list */
2339 for (i = 0; i < llist->dflt_size; i++) {
2340 if (ly_strequal(llist->dflt[i], value, 1)) {
2341 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2342 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2343 goto error;
2344 }
2345 }
2346 /* store it in target node */
2347 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2348
2349 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2350 ly_set_add(dflt_check, dev_target, 0);
2351 }
2352 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002353 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002354 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002355
2356 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2357 /* consolidate the final list in the target after removing items from it */
2358 llist = (struct lys_node_leaflist *)dev_target;
2359 for (i = j = 0; j < llist->dflt_size; j++) {
2360 llist->dflt[i] = llist->dflt[j];
2361 if (llist->dflt[i]) {
2362 i++;
2363 }
2364 }
2365 llist->dflt_size = i + 1;
2366 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002367 }
2368
Michal Vasko43a1feb2016-03-07 12:03:02 +01002369 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002370 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002371 value = NULL;
2372 rc = EXIT_SUCCESS;
2373 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2374 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2375 rc = unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, value = leaf->dflt);
2376 } else { /* LYS_LEAFLIST */
2377 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2378 for (j = 0; j < llist->dflt_size; j++) {
2379 rc = unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, value = llist->dflt[j]);
2380 if (rc == -1) {
2381 break;
2382 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002383 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002384
2385 }
2386 if (rc == -1) {
2387 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2388 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2389 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2390 dev->target_name);
2391 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002392 }
2393 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002394
Radek Krejci27fe55e2016-09-13 17:13:35 +02002395 /* mark all the affected modules as deviated and implemented */
2396 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2397 mod = lys_node_module(parent);
2398 if (module != mod) {
2399 mod->deviated = 1;
2400 lys_set_implemented(mod);
2401 }
2402 }
2403
Radek Krejcid5a5c282016-08-15 15:38:08 +02002404 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002405 return EXIT_SUCCESS;
2406
2407error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002408 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002409 return EXIT_FAILURE;
2410}
2411
Michal Vasko0d343d12015-08-24 14:57:36 +02002412/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002413static int
Radek Krejcib8048692015-08-05 13:36:34 +02002414fill_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 +02002415 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002416{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002417 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002418 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002419 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002420 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002421
Michal Vasko591e0b22015-08-13 13:53:43 +02002422 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002424 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002425 if (!aug->target_name) {
2426 goto error;
2427 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002428 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002429
Michal Vasko1d87a922015-08-21 12:57:16 +02002430 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002431 goto error;
2432 }
2433
2434 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002435 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2436 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002437 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002438 continue;
2439 }
2440
Radek Krejci3cf9e222015-06-18 11:37:50 +02002441 if (!strcmp(child->name, "if-feature")) {
2442 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002443 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002444 } else if (!strcmp(child->name, "when")) {
2445 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002446 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002447 goto error;
2448 }
2449
2450 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002451 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002452 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002453 goto error;
2454 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002455 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002456 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002457
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002458 /* check allowed data sub-statements */
2459 } else if (!strcmp(child->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002460 node = read_yin_container(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002461 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002462 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002463 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002464 node = read_yin_leaf(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002465 } else if (!strcmp(child->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002466 node = read_yin_list(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002467 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002468 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002469 } else if (!strcmp(child->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002470 node = read_yin_case(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002471 } else if (!strcmp(child->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002472 node = read_yin_case(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002473 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002474 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYXML, 1, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02002475 } else if (!strcmp(child->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002476 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYDATA, 1, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002477 } else if (!strcmp(child->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002478 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02002479 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002480 node = read_yin_notif(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002481 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002482 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002483 goto error;
2484 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002485
Radek Krejci1d82ef62015-08-07 14:44:40 +02002486 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002487 goto error;
2488 }
2489
Radek Krejci1d82ef62015-08-07 14:44:40 +02002490 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002491 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002492 }
2493
2494 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002495 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2496 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002497 LOGMEM;
2498 goto error;
2499 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002500 }
2501
2502 LY_TREE_FOR_SAFE(yin->child, next, child) {
2503 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002504 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2505 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002506 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002507 goto error;
2508 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002509 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002510 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002511 }
2512
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002513 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002514 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002515 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002516 * when the uses does and cannot be resolved now for sure
2517 * (the grouping was not yet copied into uses).
2518 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002519 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002520 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002521 goto error;
2522 }
Michal Vasko49291b32015-08-06 09:49:41 +02002523 }
Radek Krejci106efc02015-06-10 14:36:27 +02002524
Michal Vasko508a50d2016-09-07 14:50:33 +02002525 /* check XPath dependencies */
2526 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2527 goto error;
2528 }
2529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002531
2532error:
2533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002535}
2536
Michal Vasko0d343d12015-08-24 14:57:36 +02002537/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002539fill_yin_refine(struct lys_node *uses, struct lyxml_elem *yin, struct lys_refine *rfn, struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002540{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002541 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002542 struct lyxml_elem *sub, *next;
2543 const char *value;
2544 char *endptr;
2545 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci200bf712016-08-16 17:11:04 +02002546 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002547 int r;
2548 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002549
Radek Krejci363bd4a2016-07-29 14:30:20 +02002550 assert(uses);
2551 module = uses->module; /* shorthand */
2552
Michal Vaskoe022a562016-09-27 14:24:15 +02002553 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CFG_PARSE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002554 goto error;
2555 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002556
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002557 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002558 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002559 if (!rfn->target_name) {
2560 goto error;
2561 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002562
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002563 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002564 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2565 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002566 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002567 continue;
2568 }
2569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002570 /* limited applicability */
2571 if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002572 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002574 /* check possibility of statements combination */
2575 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002576 if (c_dflt) {
2577 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002578 if (module->version < 2) {
2579 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2580 goto error;
2581 }
Radek Krejci200bf712016-08-16 17:11:04 +02002582 rfn->target_type &= LYS_LEAFLIST;
2583 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002584 if (module->version < 2) {
2585 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2586 } else {
2587 /* YANG 1.1 */
2588 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2589 }
Radek Krejci200bf712016-08-16 17:11:04 +02002590 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002591 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002592 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2593 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 goto error;
2595 }
2596 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002597 if (module->version < 2) {
2598 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2599 } else {
2600 /* YANG 1.1 */
2601 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2602 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002603 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002604
Radek Krejci200bf712016-08-16 17:11:04 +02002605 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002606 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 } else if (!strcmp(sub->name, "mandatory")) {
2608 /* leaf, choice or anyxml */
2609 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002610 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 goto error;
2612 }
2613 /* just checking the flags in leaf is not sufficient, we would allow
2614 * multiple mandatory statements with the "false" value
2615 */
2616 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002617
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002618 /* check possibility of statements combination */
2619 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002620 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002621 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002622 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2623 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002624 goto error;
2625 }
2626 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002627 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002630 GETVAL(value, sub, "value");
2631 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002632 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002634 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002635 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002636 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002637 goto error;
2638 }
2639 } else if (!strcmp(sub->name, "min-elements")) {
2640 /* list or leaf-list */
2641 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002642 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 goto error;
2644 }
2645 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 /* check possibility of statements combination */
2648 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002649 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002650 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002651 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2652 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002653 goto error;
2654 }
2655 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002656 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002657 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002659 GETVAL(value, sub, "value");
2660 while (isspace(value[0])) {
2661 value++;
2662 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002664 /* convert it to uint32_t */
2665 errno = 0;
2666 endptr = NULL;
2667 val = strtoul(value, &endptr, 10);
2668 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002669 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002670 goto error;
2671 }
2672 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002673 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 } else if (!strcmp(sub->name, "max-elements")) {
2675 /* list or leaf-list */
2676 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002677 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 goto error;
2679 }
2680 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002682 /* check possibility of statements combination */
2683 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002684 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002685 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002686 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2687 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 goto error;
2689 }
2690 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002691 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002694 GETVAL(value, sub, "value");
2695 while (isspace(value[0])) {
2696 value++;
2697 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002698
Radek Krejci0d7b2472016-02-12 11:11:03 +01002699 if (!strcmp(value, "unbounded")) {
2700 rfn->mod.list.max = 0;
2701 } else {
2702 /* convert it to uint32_t */
2703 errno = 0;
2704 endptr = NULL;
2705 val = strtoul(value, &endptr, 10);
2706 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002707 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002708 goto error;
2709 }
2710 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002711 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002712 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 } else if (!strcmp(sub->name, "presence")) {
2714 /* container */
2715 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002716 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002717 goto error;
2718 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 /* check possibility of statements combination */
2721 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002722 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002724 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2725 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002726 goto error;
2727 }
2728 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002729 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002732 GETVAL(value, sub, "value");
2733 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2734 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002735 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 /* check possibility of statements combination */
2737 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002738 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002740 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2741 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002742 goto error;
2743 }
2744 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002745 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002749 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002750
Radek Krejci363bd4a2016-07-29 14:30:20 +02002751 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2752 /* leaf, leaf-list, list, container or anyxml */
2753 /* check possibility of statements combination */
2754 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002755 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002756 if (!rfn->target_type) {
2757 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2758 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2759 goto error;
2760 }
2761 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002762 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002763 }
2764
2765 c_ftrs++;
2766 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002767 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002768 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 goto error;
2770 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002771
Michal Vasko345da0a2015-12-02 10:35:55 +01002772 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002773 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002775 /* process nodes with cardinality of 0..n */
2776 if (c_must) {
2777 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002778 if (!rfn->must) {
2779 LOGMEM;
2780 goto error;
2781 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002783 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002784 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002785 if (!rfn->iffeature) {
2786 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002787 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002789 }
Radek Krejci200bf712016-08-16 17:11:04 +02002790 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002791 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002792 if (!rfn->dflt) {
2793 LOGMEM;
2794 goto error;
2795 }
2796 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002797
Radek Krejci363bd4a2016-07-29 14:30:20 +02002798 LY_TREE_FOR(yin->child, sub) {
2799 if (!strcmp(sub->name, "if-feature")) {
2800 r = fill_yin_iffeature(uses, sub, &rfn->iffeature[rfn->iffeature_size], unres);
2801 rfn->iffeature_size++;
2802 if (r) {
2803 goto error;
2804 }
Radek Krejci200bf712016-08-16 17:11:04 +02002805 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002806 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2807 rfn->must_size++;
2808 if (r) {
2809 goto error;
2810 }
Radek Krejci200bf712016-08-16 17:11:04 +02002811 } else { /* default */
2812 GETVAL(value, sub, "value");
2813
2814 /* check for duplicity */
2815 for (r = 0; r < rfn->dflt_size; r++) {
2816 if (ly_strequal(rfn->dflt[r], value, 1)) {
2817 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2818 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2819 goto error;
2820 }
2821 }
2822 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02002823 }
2824 }
2825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002827
2828error:
2829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002831}
2832
Michal Vasko0d343d12015-08-24 14:57:36 +02002833/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834static int
Radek Krejcib8048692015-08-05 13:36:34 +02002835fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002836{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 struct lyxml_elem *child;
2838 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002841 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2842 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002843 continue;
2844 }
2845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002846 if (!strcmp(child->name, "prefix")) {
2847 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002848 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 goto error;
2850 }
2851 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2852 } else if (!strcmp(child->name, "revision-date")) {
2853 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002854 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2855 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 }
2857 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002858 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002859 goto error;
2860 }
2861 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002862 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002863 if (imp->dsc) {
2864 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2865 goto error;
2866 }
2867 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2868 if (!imp->dsc) {
2869 goto error;
2870 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002871 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002872 if (imp->ref) {
2873 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2874 goto error;
2875 }
2876 imp->ref = read_yin_subnode(module->ctx, child, "text");
2877 if (!imp->ref) {
2878 goto error;
2879 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002880 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002881 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002882 goto error;
2883 }
2884 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 /* check mandatory information */
2887 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002888 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002889 goto error;
2890 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002893
Pavol Vicane994fda2016-03-22 10:47:58 +01002894 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002895
2896error:
2897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002898 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002899}
2900
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002901/* logs directly
2902 * returns:
2903 * 0 - inc successfully filled
2904 * -1 - error, inc is cleaned
2905 * 1 - duplication, ignore the inc structure, inc is cleaned
2906 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002908fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2909 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002910{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 struct lyxml_elem *child;
2912 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002915 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2916 /* garbage */
2917 continue;
2918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 if (!strcmp(child->name, "revision-date")) {
2920 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002921 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922 goto error;
2923 }
2924 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002925 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 goto error;
2927 }
2928 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002929 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002930 if (inc->dsc) {
2931 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2932 goto error;
2933 }
2934 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2935 if (!inc->dsc) {
2936 goto error;
2937 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002938 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002939 if (inc->ref) {
2940 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2941 goto error;
2942 }
2943 inc->ref = read_yin_subnode(module->ctx, child, "text");
2944 if (!inc->ref) {
2945 goto error;
2946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002948 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002949 goto error;
2950 }
2951 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002953 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002954
Pavol Vican0adf01d2016-03-22 12:29:33 +01002955 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002956
2957error:
2958
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002959 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002960}
2961
Michal Vasko0d343d12015-08-24 14:57:36 +02002962/* logs directly
2963 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002964 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002965 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002966 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002967 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002968static int
Radek Krejcib8048692015-08-05 13:36:34 +02002969read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002970 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002971{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002972 const char *value;
2973 struct lyxml_elem *sub, *next;
2974 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002976 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002977 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 if (opt & OPT_IDENT) {
2981 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002982 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 goto error;
2984 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002985 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002986 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002987
Radek Krejci6764bb32015-07-03 15:16:04 +02002988 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002989 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002990 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002991 }
2992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002993 /* process local parameters */
2994 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002995 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002996 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002997 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002998 continue;
2999 }
3000 if (strcmp(sub->ns->value, LY_NSYIN)) {
3001 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02003002 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003003 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003004 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02003005 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003006 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02003007 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003008 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02003009 goto error;
3010 }
3011 }
3012
3013 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003014 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003015 continue;
3016 }
3017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003019 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003020 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 goto error;
3022 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003023 node->dsc = read_yin_subnode(ctx, sub, "text");
3024 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003025 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003026 }
3027 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003028 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003029 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 goto error;
3031 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003032 node->ref = read_yin_subnode(ctx, sub, "text");
3033 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003034 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 }
3036 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003037 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003038 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 goto error;
3040 }
3041 GETVAL(value, sub, "value");
3042 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003043 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003045 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003046 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003047 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003049 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003050 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003052 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3053 if (opt & OPT_CFG_PARSE) {
3054 if (node->flags & LYS_CONFIG_MASK) {
3055 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3056 goto error;
3057 }
3058 GETVAL(value, sub, "value");
3059 if (!strcmp(value, "false")) {
3060 node->flags |= LYS_CONFIG_R;
3061 } else if (!strcmp(value, "true")) {
3062 node->flags |= LYS_CONFIG_W;
3063 } else {
3064 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3065 goto error;
3066 }
3067 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003070 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 continue;
3072 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003073 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003074 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003075
Michal Vaskoe022a562016-09-27 14:24:15 +02003076 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02003078 if (parent && (parent->flags & LYS_CONFIG_R)) {
3079 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 } else {
3081 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003082 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 }
3084 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003087
3088error:
3089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003091}
3092
Michal Vasko0d343d12015-08-24 14:57:36 +02003093/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003094static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003095read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003096{
Radek Krejci76512572015-08-04 09:47:08 +02003097 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003098 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003099 const char *value;
3100
3101 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003102 if (!retval) {
3103 LOGMEM;
3104 return NULL;
3105 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003106
3107 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003108 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003109 if (!retval->cond) {
3110 goto error;
3111 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003112
Radek Krejci73adb602015-07-02 18:07:40 +02003113 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003114 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3115 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003116 continue;
3117 }
3118
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003119 if (!strcmp(child->name, "description")) {
3120 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003121 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003122 goto error;
3123 }
3124 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3125 if (!retval->dsc) {
3126 goto error;
3127 }
3128 } else if (!strcmp(child->name, "reference")) {
3129 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003130 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003131 goto error;
3132 }
3133 retval->ref = read_yin_subnode(module->ctx, child, "text");
3134 if (!retval->ref) {
3135 goto error;
3136 }
3137 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003138 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003139 goto error;
3140 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003141 }
3142
3143 return retval;
3144
3145error:
3146
Michal Vasko0308dd62015-10-07 09:14:40 +02003147 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003148 return NULL;
3149}
3150
Michal Vasko0d343d12015-08-24 14:57:36 +02003151/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003152static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003153read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003154 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003155{
Michal Vasko29fc0182015-08-24 15:02:39 +02003156 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003157 struct lys_node_case *cs;
3158 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02003159 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003160
Radek Krejcie867c852015-08-27 09:52:34 +02003161 /* init */
3162 memset(&root, 0, sizeof root);
3163
Radek Krejci1d82ef62015-08-07 14:44:40 +02003164 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003165 if (!cs) {
3166 LOGMEM;
3167 return NULL;
3168 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003169 cs->nodetype = LYS_CASE;
3170 cs->prev = (struct lys_node *)cs;
3171 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003172
Michal Vaskoe022a562016-09-27 14:24:15 +02003173 if (read_yin_common(module, parent, retval, yin,
3174 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0) | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 goto error;
3176 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003177
Radek Krejcia9544502015-08-14 08:24:29 +02003178 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3179
Michal Vasko3a0043f2015-08-12 12:11:30 +02003180 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003181 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003182 goto error;
3183 }
3184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 /* process choice's specific children */
3186 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003187 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3188 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003189 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003190 continue;
3191 }
3192
Michal Vasko29fc0182015-08-24 15:02:39 +02003193 if (!strcmp(sub->name, "container") ||
3194 !strcmp(sub->name, "leaf-list") ||
3195 !strcmp(sub->name, "leaf") ||
3196 !strcmp(sub->name, "list") ||
3197 !strcmp(sub->name, "uses") ||
3198 !strcmp(sub->name, "choice") ||
3199 !strcmp(sub->name, "anyxml")) {
3200
Michal Vaskof3930de2015-10-22 12:03:59 +02003201 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003202 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003203 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003204 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01003205 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02003206 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003207 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003208 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003209 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003210 goto error;
3211 }
3212
Radek Krejci1d82ef62015-08-07 14:44:40 +02003213 cs->when = read_yin_when(module, sub);
3214 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003215 goto error;
3216 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003217
Michal Vasko345da0a2015-12-02 10:35:55 +01003218 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003220 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003224
Radek Krejci3cf9e222015-06-18 11:37:50 +02003225 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003226 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3227 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003228 LOGMEM;
3229 goto error;
3230 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003231 }
Radek Krejci73adb602015-07-02 18:07:40 +02003232 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003233 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
3234 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003235 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003236 goto error;
3237 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 }
Radek Krejcib388c152015-06-04 17:03:03 +02003239
Michal Vasko29fc0182015-08-24 15:02:39 +02003240 /* last part - process data nodes */
3241 LY_TREE_FOR_SAFE(root.child, next, sub) {
3242 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003243 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003244 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003245 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003246 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003247 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003248 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003249 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003250 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003251 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003252 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003253 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003254 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003255 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003256 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003257 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003258 }
3259 if (!node) {
3260 goto error;
3261 }
3262
Michal Vasko345da0a2015-12-02 10:35:55 +01003263 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003264 }
3265
Michal Vasko508a50d2016-09-07 14:50:33 +02003266 /* check XPath dependencies */
3267 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3268 goto error;
3269 }
3270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003272
3273error:
3274
Michal Vasko29fc0182015-08-24 15:02:39 +02003275 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003276 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003277 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003278 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003281}
3282
Michal Vasko0d343d12015-08-24 14:57:36 +02003283/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003284static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003285read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3286 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003287{
Radek Krejci629cdef2016-06-06 15:06:36 +02003288 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003290 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003291 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003292 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02003293 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003295 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003296 if (!choice) {
3297 LOGMEM;
3298 return NULL;
3299 }
Radek Krejci76512572015-08-04 09:47:08 +02003300 choice->nodetype = LYS_CHOICE;
3301 choice->prev = (struct lys_node *)choice;
3302 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003303
Michal Vaskoe022a562016-09-27 14:24:15 +02003304 if (read_yin_common(module, parent, retval, yin,
3305 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3306 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 goto error;
3308 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003309
Radek Krejcia9544502015-08-14 08:24:29 +02003310 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3311
Michal Vasko3a0043f2015-08-12 12:11:30 +02003312 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003313 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003314 goto error;
3315 }
3316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 /* process choice's specific children */
3318 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003319 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3320 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003321 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003322 continue;
3323 }
3324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003326 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 goto error;
3328 }
3329 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003330 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 goto error;
3332 }
3333 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003334 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 goto error;
3336 }
3337 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003338 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 goto error;
3340 }
3341 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003342 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
3344 }
3345 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003346 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003347 goto error;
3348 }
3349 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003350 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003351 goto error;
3352 }
3353 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003354 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003355 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 goto error;
3357 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003358 dflt = sub;
3359 lyxml_unlink_elem(ctx, dflt, 0);
3360
Radek Krejcif9a312c2016-06-06 15:14:30 +02003361 continue;
3362 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 } else if (!strcmp(sub->name, "mandatory")) {
3365 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003366 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 goto error;
3368 }
3369 /* just checking the flags in leaf is not sufficient, we would allow
3370 * multiple mandatory statements with the "false" value
3371 */
3372 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003374 GETVAL(value, sub, "value");
3375 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003376 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003377 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003378 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003379 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003380 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003381 goto error;
3382 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003383 } else if (!strcmp(sub->name, "when")) {
3384 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003385 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003386 goto error;
3387 }
3388
3389 choice->when = read_yin_when(module, sub);
3390 if (!choice->when) {
3391 goto error;
3392 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003393 } else if (!strcmp(sub->name, "if-feature")) {
3394 c_ftrs++;
3395
Michal Vasko345da0a2015-12-02 10:35:55 +01003396 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003397 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003398 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003399 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02003400 goto error;
3401 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003402 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003403 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003406
Radek Krejci1d82ef62015-08-07 14:44:40 +02003407 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003408 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003410
Radek Krejci3cf9e222015-06-18 11:37:50 +02003411 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003412 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3413 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003414 LOGMEM;
3415 goto error;
3416 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003417 }
3418
Radek Krejci73adb602015-07-02 18:07:40 +02003419 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003420 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
3421 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003422 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003423 goto error;
3424 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003425 }
3426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003428 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003429 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
3430 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 goto error;
3432 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003433
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003435 if (dflt) {
3436 GETVAL(value, dflt, "value");
3437 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003438 goto error;
3439 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003440 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003442
Michal Vasko508a50d2016-09-07 14:50:33 +02003443 /* check XPath dependencies */
3444 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3445 goto error;
3446 }
3447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003449
3450error:
3451
Radek Krejci629cdef2016-06-06 15:06:36 +02003452 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003453 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003456}
3457
Michal Vasko0d343d12015-08-24 14:57:36 +02003458/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003459static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003460read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
3461 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003462{
Radek Krejci76512572015-08-04 09:47:08 +02003463 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003464 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 struct lyxml_elem *sub, *next;
3466 const char *value;
3467 int r;
3468 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003469 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003472 if (!anyxml) {
3473 LOGMEM;
3474 return NULL;
3475 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003476 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003477 anyxml->prev = (struct lys_node *)anyxml;
3478 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003479
Michal Vaskoe022a562016-09-27 14:24:15 +02003480 if (read_yin_common(module, parent, retval, yin,
3481 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3482 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 goto error;
3484 }
Radek Krejci863c2852015-06-03 15:47:11 +02003485
Radek Krejcia9544502015-08-14 08:24:29 +02003486 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003487
Radek Krejciadb30652016-07-11 15:27:07 +02003488 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003489 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003490 goto error;
3491 }
3492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003494 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3495 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003496 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003497 continue;
3498 }
3499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 if (!strcmp(sub->name, "mandatory")) {
3501 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003502 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003503 goto error;
3504 }
3505 /* just checking the flags in leaf is not sufficient, we would allow
3506 * multiple mandatory statements with the "false" value
3507 */
3508 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 GETVAL(value, sub, "value");
3511 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003512 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003513 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003514 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003515 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003516 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 goto error;
3518 }
3519 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003520 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003521 } else if (!strcmp(sub->name, "when")) {
3522 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003523 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003524 goto error;
3525 }
3526
3527 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003528 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003529 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003530 goto error;
3531 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003532 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 } else if (!strcmp(sub->name, "must")) {
3534 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003535 } else if (!strcmp(sub->name, "if-feature")) {
3536 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003539 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 }
3542 }
Radek Krejci863c2852015-06-03 15:47:11 +02003543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 /* middle part - process nodes with cardinality of 0..n */
3545 if (c_must) {
3546 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003547 if (!anyxml->must) {
3548 LOGMEM;
3549 goto error;
3550 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003551 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003552 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003553 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3554 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003555 LOGMEM;
3556 goto error;
3557 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003558 }
Radek Krejci863c2852015-06-03 15:47:11 +02003559
Radek Krejci73adb602015-07-02 18:07:40 +02003560 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003562 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3563 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 if (r) {
3565 goto error;
3566 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003567 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003568 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3569 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003570 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003571 goto error;
3572 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 }
Radek Krejci863c2852015-06-03 15:47:11 +02003575
Michal Vasko508a50d2016-09-07 14:50:33 +02003576 /* check XPath dependencies */
3577 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3578 goto error;
3579 }
3580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003582
3583error:
3584
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003585 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003588}
3589
Michal Vasko0d343d12015-08-24 14:57:36 +02003590/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003591static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003592read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003593 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003594{
Radek Krejci76512572015-08-04 09:47:08 +02003595 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003596 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 struct lyxml_elem *sub, *next;
3598 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003599 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003600 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003603 if (!leaf) {
3604 LOGMEM;
3605 return NULL;
3606 }
Radek Krejci76512572015-08-04 09:47:08 +02003607 leaf->nodetype = LYS_LEAF;
3608 leaf->prev = (struct lys_node *)leaf;
3609 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003610
Michal Vaskoe022a562016-09-27 14:24:15 +02003611 if (read_yin_common(module, parent, retval, yin,
3612 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3613 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 goto error;
3615 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003616
Radek Krejcia9544502015-08-14 08:24:29 +02003617 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003618
Radek Krejciadb30652016-07-11 15:27:07 +02003619 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003620 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003621 goto error;
3622 }
3623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003625 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3626 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003627 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003628 continue;
3629 }
3630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003632 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003633 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003634 goto error;
3635 }
Michal Vasko88c29542015-11-27 14:57:53 +01003636 /* HACK for unres */
3637 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003638 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003639 /* postpone type resolution when if-feature parsing is done since we need
3640 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003641 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003642 } else if (!strcmp(sub->name, "default")) {
3643 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003644 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003645 goto error;
3646 }
3647 GETVAL(value, sub, "value");
3648 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3649 } else if (!strcmp(sub->name, "units")) {
3650 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003651 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 goto error;
3653 }
3654 GETVAL(value, sub, "name");
3655 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3656 } else if (!strcmp(sub->name, "mandatory")) {
3657 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003658 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659 goto error;
3660 }
3661 /* just checking the flags in leaf is not sufficient, we would allow
3662 * multiple mandatory statements with the "false" value
3663 */
3664 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 GETVAL(value, sub, "value");
3667 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003668 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003669 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003670 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003671 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003672 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003673 goto error;
3674 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003675 } else if (!strcmp(sub->name, "when")) {
3676 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003677 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003678 goto error;
3679 }
3680
3681 leaf->when = read_yin_when(module, sub);
3682 if (!leaf->when) {
3683 goto error;
3684 }
3685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003687 c_must++;
3688 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 } else if (!strcmp(sub->name, "if-feature")) {
3690 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003692
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003694 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003697
Michal Vasko88c29542015-11-27 14:57:53 +01003698 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003702 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003703 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 goto error;
3705 }
Michal Vasko478c4652016-07-21 12:55:01 +02003706 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3707 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3708 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3709 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3710 goto error;
3711 }
3712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 /* middle part - process nodes with cardinality of 0..n */
3714 if (c_must) {
3715 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003716 if (!leaf->must) {
3717 LOGMEM;
3718 goto error;
3719 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003721 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003722 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3723 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003724 LOGMEM;
3725 goto error;
3726 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003727 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003728
Radek Krejci73adb602015-07-02 18:07:40 +02003729 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003731 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3732 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 if (r) {
3734 goto error;
3735 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003736 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003737 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3738 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003739 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003740 goto error;
3741 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003744
Radek Krejcicbb473e2016-09-16 14:48:32 +02003745 /* finalize type parsing */
3746 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
3747 leaf->type.der = NULL;
3748 goto error;
3749 }
3750
3751 /* check default value (if not defined, there still could be some restrictions
3752 * that need to be checked against a default value from a derived type) */
3753 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3754 goto error;
3755 }
3756
Michal Vasko508a50d2016-09-07 14:50:33 +02003757 /* check XPath dependencies */
3758 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3759 goto error;
3760 }
3761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763
3764error:
3765
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003766 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003768 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769}
3770
Michal Vasko0d343d12015-08-24 14:57:36 +02003771/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003772static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003773read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003774 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003775{
Radek Krejci76512572015-08-04 09:47:08 +02003776 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003777 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003778 struct lyxml_elem *sub, *next;
3779 const char *value;
3780 char *endptr;
3781 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003782 int r, has_type = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003783 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003787 if (!llist) {
3788 LOGMEM;
3789 return NULL;
3790 }
Radek Krejci76512572015-08-04 09:47:08 +02003791 llist->nodetype = LYS_LEAFLIST;
3792 llist->prev = (struct lys_node *)llist;
3793 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003794
Michal Vaskoe022a562016-09-27 14:24:15 +02003795 if (read_yin_common(module, parent, retval, yin,
3796 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3797 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 goto error;
3799 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003800
Radek Krejcia9544502015-08-14 08:24:29 +02003801 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003802
Radek Krejciadb30652016-07-11 15:27:07 +02003803 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003804 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003805 goto error;
3806 }
3807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003809 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3810 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003811 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003812 continue;
3813 }
3814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003816 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003817 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 goto error;
3819 }
Michal Vasko88c29542015-11-27 14:57:53 +01003820 /* HACK for unres */
3821 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003822 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003823 /* postpone type resolution when if-feature parsing is done since we need
3824 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003825 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 } else if (!strcmp(sub->name, "units")) {
3827 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003828 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 goto error;
3830 }
3831 GETVAL(value, sub, "name");
3832 llist->units = lydict_insert(module->ctx, value, strlen(value));
3833 } else if (!strcmp(sub->name, "ordered-by")) {
3834 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003835 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 goto error;
3837 }
3838 /* just checking the flags in llist is not sufficient, we would
3839 * allow multiple ordered-by statements with the "system" value
3840 */
3841 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003842
Radek Krejci1574a8d2015-08-03 14:16:52 +02003843 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3845 * state data
3846 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003847 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 continue;
3849 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 GETVAL(value, sub, "value");
3852 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003853 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003855 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003856 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003857 } /* else system is the default value, so we can ignore it */
3858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 } else if (!strcmp(sub->name, "must")) {
3860 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003861 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003862 } else if (!strcmp(sub->name, "if-feature")) {
3863 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003864 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003865 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
3866 c_dflt++;
3867 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 } else if (!strcmp(sub->name, "min-elements")) {
3870 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003871 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 goto error;
3873 }
3874 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 GETVAL(value, sub, "value");
3877 while (isspace(value[0])) {
3878 value++;
3879 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003881 /* convert it to uint32_t */
3882 errno = 0;
3883 endptr = NULL;
3884 val = strtoul(value, &endptr, 10);
3885 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003886 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 goto error;
3888 }
3889 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003890 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003891 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3892 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003893 goto error;
3894 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003895 } else if (!strcmp(sub->name, "max-elements")) {
3896 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003897 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003898 goto error;
3899 }
3900 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 GETVAL(value, sub, "value");
3903 while (isspace(value[0])) {
3904 value++;
3905 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003906
Radek Krejci0d7b2472016-02-12 11:11:03 +01003907 if (!strcmp(value, "unbounded")) {
3908 llist->max = 0;
3909 } else {
3910 /* convert it to uint32_t */
3911 errno = 0;
3912 endptr = NULL;
3913 val = strtoul(value, &endptr, 10);
3914 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003915 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003916 goto error;
3917 }
3918 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003919 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003920 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3921 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003922 goto error;
3923 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003925 } else if (!strcmp(sub->name, "when")) {
3926 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003927 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003928 goto error;
3929 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003930
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003931 llist->when = read_yin_when(module, sub);
3932 if (!llist->when) {
3933 goto error;
3934 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003936 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003937 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003939
Michal Vasko88c29542015-11-27 14:57:53 +01003940 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003941 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003944 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003945 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 goto error;
3947 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 /* middle part - process nodes with cardinality of 0..n */
3950 if (c_must) {
3951 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003952 if (!llist->must) {
3953 LOGMEM;
3954 goto error;
3955 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003956 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003957 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003958 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3959 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003960 LOGMEM;
3961 goto error;
3962 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003963 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003964 if (c_dflt) {
3965 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
3966 if (!llist->dflt) {
3967 LOGMEM;
3968 goto error;
3969 }
3970 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003971
Radek Krejci73adb602015-07-02 18:07:40 +02003972 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003973 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003974 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3975 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003976 if (r) {
3977 goto error;
3978 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003979 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003980 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3981 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003982 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003983 goto error;
3984 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003985 } else if (!strcmp(sub->name, "default")) {
3986 GETVAL(value, sub, "value");
3987
Radek Krejciac1a52c2016-09-15 14:42:40 +02003988 /* check for duplicity in case of configuration data,
3989 * in case of status data duplicities are allowed */
3990 if (llist->flags & LYS_CONFIG_W) {
3991 for (r = 0; r < llist->dflt_size; r++) {
3992 if (ly_strequal(llist->dflt[r], value, 1)) {
3993 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3994 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3995 goto error;
3996 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003997 }
3998 }
3999 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
4000 }
4001 }
4002
Radek Krejcicbb473e2016-09-16 14:48:32 +02004003 /* finalize type parsing */
4004 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4005 llist->type.der = NULL;
4006 goto error;
4007 }
4008
Radek Krejcid5a5c282016-08-15 15:38:08 +02004009 if (llist->dflt_size && llist->min) {
Radek Krejci200bf712016-08-16 17:11:04 +02004010 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "leaf-list");
Radek Krejcid5a5c282016-08-15 15:38:08 +02004011 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
4012 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4013 goto error;
4014 }
4015
4016 /* check default value (if not defined, there still could be some restrictions
4017 * that need to be checked against a default value from a derived type) */
4018 for (r = 0; r < llist->dflt_size; r++) {
4019 if (unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, llist->dflt[r]) == -1) {
4020 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004022 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004023
Michal Vasko508a50d2016-09-07 14:50:33 +02004024 /* check XPath dependencies */
4025 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4026 goto error;
4027 }
4028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004029 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004030
4031error:
4032
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004033 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004036}
4037
Michal Vasko0d343d12015-08-24 14:57:36 +02004038/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004039static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004040read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004041 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004042{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004043 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004044 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004046 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004047 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004048 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02004049 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 char *auxs;
4051 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004053 /* init */
4054 memset(&root, 0, sizeof root);
4055 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004057 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004058 if (!list) {
4059 LOGMEM;
4060 return NULL;
4061 }
Radek Krejci76512572015-08-04 09:47:08 +02004062 list->nodetype = LYS_LIST;
4063 list->prev = (struct lys_node *)list;
4064 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004065
Michal Vaskoe022a562016-09-27 14:24:15 +02004066 if (read_yin_common(module, parent, retval, yin,
4067 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
4068 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004069 goto error;
4070 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004071
Radek Krejcia9544502015-08-14 08:24:29 +02004072 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4073
Radek Krejciadb30652016-07-11 15:27:07 +02004074 /* insert the node into the schema tree */
4075 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4076 goto error;
4077 }
4078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004079 /* process list's specific children */
4080 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004081 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4082 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004083 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004084 continue;
4085 }
4086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004087 /* data statements */
4088 if (!strcmp(sub->name, "container") ||
4089 !strcmp(sub->name, "leaf-list") ||
4090 !strcmp(sub->name, "leaf") ||
4091 !strcmp(sub->name, "list") ||
4092 !strcmp(sub->name, "choice") ||
4093 !strcmp(sub->name, "uses") ||
4094 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004095 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004096 !strcmp(sub->name, "action") ||
4097 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004098 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004099 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004101 /* array counters */
4102 } else if (!strcmp(sub->name, "key")) {
4103 /* check cardinality 0..1 */
4104 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004105 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106 goto error;
4107 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02004108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004109 /* count the number of keys */
4110 GETVAL(value, sub, "value");
4111 key_str = value;
4112 while ((value = strpbrk(value, " \t\n"))) {
4113 list->keys_size++;
4114 while (isspace(*value)) {
4115 value++;
4116 }
4117 }
4118 list->keys_size++;
4119 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004120 if (!list->keys) {
4121 LOGMEM;
4122 goto error;
4123 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004124 } else if (!strcmp(sub->name, "unique")) {
4125 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004126 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004127 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 } else if (!strcmp(sub->name, "typedef")) {
4129 c_tpdf++;
4130 } else if (!strcmp(sub->name, "must")) {
4131 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004132 } else if (!strcmp(sub->name, "if-feature")) {
4133 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 /* optional stetments */
4136 } else if (!strcmp(sub->name, "ordered-by")) {
4137 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004138 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004139 goto error;
4140 }
4141 /* just checking the flags in llist is not sufficient, we would
4142 * allow multiple ordered-by statements with the "system" value
4143 */
4144 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004145
Radek Krejci1574a8d2015-08-03 14:16:52 +02004146 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004147 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4148 * state data
4149 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004150 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151 continue;
4152 }
Radek Krejci345ad742015-06-03 11:04:18 +02004153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 GETVAL(value, sub, "value");
4155 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004156 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004158 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004159 goto error;
4160 }
4161 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004162 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004163 } else if (!strcmp(sub->name, "min-elements")) {
4164 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004165 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004166 goto error;
4167 }
4168 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004170 GETVAL(value, sub, "value");
4171 while (isspace(value[0])) {
4172 value++;
4173 }
Radek Krejci345ad742015-06-03 11:04:18 +02004174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004175 /* convert it to uint32_t */
4176 errno = 0;
4177 auxs = NULL;
4178 val = strtoul(value, &auxs, 10);
4179 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004180 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004181 goto error;
4182 }
4183 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004184 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004185 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4186 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004187 lyxml_free(module->ctx, sub);
4188 goto error;
4189 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004190 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004191 } else if (!strcmp(sub->name, "max-elements")) {
4192 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004193 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004194 goto error;
4195 }
4196 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004198 GETVAL(value, sub, "value");
4199 while (isspace(value[0])) {
4200 value++;
4201 }
Radek Krejci345ad742015-06-03 11:04:18 +02004202
Radek Krejci0d7b2472016-02-12 11:11:03 +01004203 if (!strcmp(value, "unbounded")) {
4204 list->max = 0;;
4205 } else {
4206 /* convert it to uint32_t */
4207 errno = 0;
4208 auxs = NULL;
4209 val = strtoul(value, &auxs, 10);
4210 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004211 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004212 goto error;
4213 }
4214 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004215 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004216 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4217 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004218 goto error;
4219 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004220 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004221 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004222 } else if (!strcmp(sub->name, "when")) {
4223 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004225 goto error;
4226 }
4227
4228 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004229 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004230 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004231 goto error;
4232 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004233 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004234 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004235 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004236 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 }
4238 }
Radek Krejci345ad742015-06-03 11:04:18 +02004239
Michal Vaskoe022a562016-09-27 14:24:15 +02004240 /* check - if list is configuration, key statement is mandatory
4241 * (but only if we are not in a grouping or augment, then the check is deferred) */
4242 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
4243 if (!node && (list->flags & LYS_CONFIG_W) && !key_str) {
4244 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004245 goto error;
4246 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4249 if (c_tpdf) {
4250 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004251 if (!list->tpdf) {
4252 LOGMEM;
4253 goto error;
4254 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004256 if (c_must) {
4257 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004258 if (!list->must) {
4259 LOGMEM;
4260 goto error;
4261 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004262 }
4263 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004264 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4265 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004266 LOGMEM;
4267 goto error;
4268 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004269 }
Radek Krejci73adb602015-07-02 18:07:40 +02004270 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004272 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4273 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004274 if (r) {
4275 goto error;
4276 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004277 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004278 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
4279 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004280 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004281 goto error;
4282 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004283 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004284 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4285 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004286 if (r) {
4287 goto error;
4288 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 }
4290 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004292 /* last part - process data nodes */
4293 LY_TREE_FOR_SAFE(root.child, next, sub) {
4294 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004295 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004297 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004299 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004300 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004301 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004303 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004304 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004305 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004307 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004309 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004310 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004311 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004312 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004313 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004314 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004315 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004316 } else {
4317 LOGINT;
4318 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004319 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004320 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 goto error;
4322 }
Radek Krejci73adb602015-07-02 18:07:40 +02004323
Michal Vasko345da0a2015-12-02 10:35:55 +01004324 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004326
Radek Krejci461efb92016-02-12 15:52:18 +01004327 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004328 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004329 goto error;
4330 }
4331 } /* 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 +02004332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004333 /* process unique statements */
4334 if (c_uniq) {
4335 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004336 if (!list->unique) {
4337 LOGMEM;
4338 goto error;
4339 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004340
Radek Krejci461efb92016-02-12 15:52:18 +01004341 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4342 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4343 list->unique_size++;
4344 if (r) {
4345 goto error;
4346 }
4347
4348 lyxml_free(module->ctx, sub);
4349 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004351
Michal Vasko508a50d2016-09-07 14:50:33 +02004352 /* check XPath dependencies */
4353 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4354 goto error;
4355 }
4356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004358
4359error:
4360
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004361 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004363 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 }
4365 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004366 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004369 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004370}
4371
Michal Vasko0d343d12015-08-24 14:57:36 +02004372/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004373static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004374read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004375 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004376{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004377 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004378 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004379 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004380 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004381 const char *value;
4382 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004383 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 /* init */
4386 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004389 if (!cont) {
4390 LOGMEM;
4391 return NULL;
4392 }
Radek Krejci76512572015-08-04 09:47:08 +02004393 cont->nodetype = LYS_CONTAINER;
4394 cont->prev = (struct lys_node *)cont;
4395 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004396
Michal Vaskoe022a562016-09-27 14:24:15 +02004397 if (read_yin_common(module, parent, retval, yin,
4398 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
4399 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 goto error;
4401 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004402
Radek Krejcia9544502015-08-14 08:24:29 +02004403 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4404
Radek Krejciadb30652016-07-11 15:27:07 +02004405 /* insert the node into the schema tree */
4406 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4407 goto error;
4408 }
4409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 /* process container's specific children */
4411 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02004412 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004413 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004414 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004415 continue;
4416 }
4417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 if (!strcmp(sub->name, "presence")) {
4419 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004420 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004421 goto error;
4422 }
4423 GETVAL(value, sub, "value");
4424 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004425
Michal Vasko345da0a2015-12-02 10:35:55 +01004426 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004427 } else if (!strcmp(sub->name, "when")) {
4428 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004429 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004430 goto error;
4431 }
4432
4433 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004434 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004435 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004436 goto error;
4437 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004438 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 /* data statements */
4441 } else if (!strcmp(sub->name, "container") ||
4442 !strcmp(sub->name, "leaf-list") ||
4443 !strcmp(sub->name, "leaf") ||
4444 !strcmp(sub->name, "list") ||
4445 !strcmp(sub->name, "choice") ||
4446 !strcmp(sub->name, "uses") ||
4447 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004448 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004449 !strcmp(sub->name, "action") ||
4450 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004451 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004452 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 /* array counters */
4455 } else if (!strcmp(sub->name, "typedef")) {
4456 c_tpdf++;
4457 } else if (!strcmp(sub->name, "must")) {
4458 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004459 } else if (!strcmp(sub->name, "if-feature")) {
4460 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004462 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 }
4465 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4468 if (c_tpdf) {
4469 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004470 if (!cont->tpdf) {
4471 LOGMEM;
4472 goto error;
4473 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 }
4475 if (c_must) {
4476 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004477 if (!cont->must) {
4478 LOGMEM;
4479 goto error;
4480 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004482 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004483 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4484 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004485 LOGMEM;
4486 goto error;
4487 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004488 }
Radek Krejci800af702015-06-02 13:46:01 +02004489
Radek Krejci73adb602015-07-02 18:07:40 +02004490 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004491 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004492 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4493 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 if (r) {
4495 goto error;
4496 }
4497 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004498 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4499 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 if (r) {
4501 goto error;
4502 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004503 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004504 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
4505 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004506 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004507 goto error;
4508 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 /* last part - process data nodes */
4513 LY_TREE_FOR_SAFE(root.child, next, sub) {
4514 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004515 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004517 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004519 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004521 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004523 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004525 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004527 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004529 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004530 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004531 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004532 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004533 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004534 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004535 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004537 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 goto error;
4539 }
Radek Krejci73adb602015-07-02 18:07:40 +02004540
Michal Vasko345da0a2015-12-02 10:35:55 +01004541 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004543
Michal Vasko508a50d2016-09-07 14:50:33 +02004544 /* check XPath dependencies */
4545 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4546 goto error;
4547 }
4548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004550
4551error:
4552
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004553 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004555 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004559}
4560
Michal Vasko0d343d12015-08-24 14:57:36 +02004561/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004562static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004563read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004564 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004565{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004567 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004568 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004569 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 int r;
4571 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 /* init */
4574 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004577 if (!grp) {
4578 LOGMEM;
4579 return NULL;
4580 }
Radek Krejci76512572015-08-04 09:47:08 +02004581 grp->nodetype = LYS_GROUPING;
4582 grp->prev = (struct lys_node *)grp;
4583 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004584
Michal Vaskoe022a562016-09-27 14:24:15 +02004585 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 goto error;
4587 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004588
Radek Krejcia9544502015-08-14 08:24:29 +02004589 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4590
Radek Krejciadb30652016-07-11 15:27:07 +02004591 /* insert the node into the schema tree */
4592 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4593 goto error;
4594 }
4595
Radek Krejci1d82ef62015-08-07 14:44:40 +02004596 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004597 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4598 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004599 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004600 continue;
4601 }
4602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004603 /* data statements */
4604 if (!strcmp(sub->name, "container") ||
4605 !strcmp(sub->name, "leaf-list") ||
4606 !strcmp(sub->name, "leaf") ||
4607 !strcmp(sub->name, "list") ||
4608 !strcmp(sub->name, "choice") ||
4609 !strcmp(sub->name, "uses") ||
4610 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004611 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02004612 !strcmp(sub->name, "action") ||
4613 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004614 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004615 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 /* array counters */
4618 } else if (!strcmp(sub->name, "typedef")) {
4619 c_tpdf++;
4620 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004621 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 goto error;
4623 }
4624 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4627 if (c_tpdf) {
4628 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004629 if (!grp->tpdf) {
4630 LOGMEM;
4631 goto error;
4632 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004634 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004635 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4636 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004637 if (r) {
4638 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004639 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004643 if (!root.child) {
4644 LOGWRN("Grouping \"%s\" without children.", retval->name);
4645 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 LY_TREE_FOR_SAFE(root.child, next, sub) {
4647 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004648 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004650 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004652 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004654 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004656 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004658 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004660 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004662 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004663 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004664 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004665 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004666 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02004667 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004668 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004670 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 goto error;
4672 }
Radek Krejci73adb602015-07-02 18:07:40 +02004673
Michal Vasko345da0a2015-12-02 10:35:55 +01004674 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004675 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004678
4679error:
4680
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004681 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004683 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004687}
4688
Michal Vasko0d343d12015-08-24 14:57:36 +02004689/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004690static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004691read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02004692 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004693{
Radek Krejcie0674f82015-06-15 13:58:51 +02004694 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004695 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004696 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004697 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004698 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004699 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004700
Radek Krejcie0674f82015-06-15 13:58:51 +02004701 /* init */
4702 memset(&root, 0, sizeof root);
4703
Michal Vasko38d01f72015-06-15 09:41:06 +02004704 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004705 if (!inout) {
4706 LOGMEM;
4707 return NULL;
4708 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004709 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004710
4711 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004712 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004713 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004714 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004715 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004716 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004717 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004718 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004719 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004720 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004721 }
4722
Radek Krejci76512572015-08-04 09:47:08 +02004723 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004724
Radek Krejci6a113852015-07-03 16:04:20 +02004725 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004726 goto error;
4727 }
4728
Radek Krejcia9544502015-08-14 08:24:29 +02004729 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4730
Radek Krejciadb30652016-07-11 15:27:07 +02004731 /* insert the node into the schema tree */
4732 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4733 goto error;
4734 }
4735
Michal Vasko38d01f72015-06-15 09:41:06 +02004736 /* data statements */
4737 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004738 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4739 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004740 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004741 continue;
4742 }
4743
Michal Vasko38d01f72015-06-15 09:41:06 +02004744 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 !strcmp(sub->name, "leaf-list") ||
4746 !strcmp(sub->name, "leaf") ||
4747 !strcmp(sub->name, "list") ||
4748 !strcmp(sub->name, "choice") ||
4749 !strcmp(sub->name, "uses") ||
4750 !strcmp(sub->name, "grouping") ||
4751 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004752 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004753 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004755 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004756 } else if (!strcmp(sub->name, "typedef")) {
4757 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004758
Radek Krejci1a31efe2016-07-29 11:04:16 +02004759 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004760 c_must++;
4761
Michal Vasko38d01f72015-06-15 09:41:06 +02004762 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004763 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004764 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004765 }
4766 }
4767
4768 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4769 if (c_tpdf) {
4770 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004771 if (!inout->tpdf) {
4772 LOGMEM;
4773 goto error;
4774 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004775 }
Radek Krejci19332802016-07-29 10:39:46 +02004776 if (c_must) {
4777 inout->must = calloc(c_must, sizeof *inout->must);
4778 if (!inout->must) {
4779 LOGMEM;
4780 goto error;
4781 }
4782 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004783
Radek Krejci73adb602015-07-02 18:07:40 +02004784 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004785 if (!strcmp(sub->name, "must")) {
4786 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4787 inout->must_size++;
4788 if (r) {
4789 goto error;
4790 }
4791 } else { /* typedef */
4792 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4793 inout->tpdf_size++;
4794 if (r) {
4795 goto error;
4796 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004797 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004798 }
4799
4800 /* last part - process data nodes */
4801 LY_TREE_FOR_SAFE(root.child, next, sub) {
4802 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004803 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004804 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004805 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004806 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004807 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004808 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004809 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004810 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004811 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004812 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004813 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004814 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004815 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004816 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004817 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004818 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004819 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004820 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004821 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004822 goto error;
4823 }
Radek Krejci73adb602015-07-02 18:07:40 +02004824
Michal Vasko345da0a2015-12-02 10:35:55 +01004825 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004826 }
4827
Michal Vasko508a50d2016-09-07 14:50:33 +02004828 /* check XPath dependencies */
4829 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4830 goto error;
4831 }
4832
Michal Vasko38d01f72015-06-15 09:41:06 +02004833 return retval;
4834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004836
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004837 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004838 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004839 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004840 }
4841
4842 return NULL;
4843}
4844
Michal Vasko0d343d12015-08-24 14:57:36 +02004845/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004846static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004847read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02004848 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004849{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004850 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004851 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004852 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004853 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004854 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004855 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004856
Michal Vasko6bb7fc12016-09-21 14:17:22 +02004857 if (parent && (module->version < 2)) {
4858 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "notification");
4859 return NULL;
4860 }
4861
Michal Vaskoc6551b32015-06-16 10:51:43 +02004862 memset(&root, 0, sizeof root);
4863
Michal Vasko0ea41032015-06-16 08:53:55 +02004864 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004865 if (!notif) {
4866 LOGMEM;
4867 return NULL;
4868 }
Radek Krejci76512572015-08-04 09:47:08 +02004869 notif->nodetype = LYS_NOTIF;
4870 notif->prev = (struct lys_node *)notif;
4871 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004872
Radek Krejci6a113852015-07-03 16:04:20 +02004873 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004874 goto error;
4875 }
4876
Radek Krejcia9544502015-08-14 08:24:29 +02004877 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4878
Radek Krejciadb30652016-07-11 15:27:07 +02004879 /* insert the node into the schema tree */
4880 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4881 goto error;
4882 }
4883
Michal Vasko0ea41032015-06-16 08:53:55 +02004884 /* process rpc's specific children */
4885 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004886 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4887 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004888 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004889 continue;
4890 }
4891
Michal Vasko0ea41032015-06-16 08:53:55 +02004892 /* data statements */
4893 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 !strcmp(sub->name, "leaf-list") ||
4895 !strcmp(sub->name, "leaf") ||
4896 !strcmp(sub->name, "list") ||
4897 !strcmp(sub->name, "choice") ||
4898 !strcmp(sub->name, "uses") ||
4899 !strcmp(sub->name, "grouping") ||
4900 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004901 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004902 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004904 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004905 } else if (!strcmp(sub->name, "typedef")) {
4906 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004907 } else if (!strcmp(sub->name, "if-feature")) {
4908 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004909 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004910 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004911 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004912 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004913 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004914 }
4915 }
4916
4917 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4918 if (c_tpdf) {
4919 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004920 if (!notif->tpdf) {
4921 LOGMEM;
4922 goto error;
4923 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004924 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004925 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004926 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4927 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004928 LOGMEM;
4929 goto error;
4930 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004931 }
Radek Krejci19332802016-07-29 10:39:46 +02004932 if (c_must) {
4933 notif->must = calloc(c_must, sizeof *notif->must);
4934 if (!notif->must) {
4935 LOGMEM;
4936 goto error;
4937 }
4938 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004939
Radek Krejci73adb602015-07-02 18:07:40 +02004940 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004941 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004942 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4943 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004944 if (r) {
4945 goto error;
4946 }
Radek Krejci96299152016-06-22 10:17:50 +02004947 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004948 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4949 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004950 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004951 goto error;
4952 }
Radek Krejci19332802016-07-29 10:39:46 +02004953 } else if (!strcmp(sub->name, "must")) {
4954 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4955 notif->must_size++;
4956 if (r) {
4957 goto error;
4958 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004959 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004960 }
4961
4962 /* last part - process data nodes */
4963 LY_TREE_FOR_SAFE(root.child, next, sub) {
4964 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004965 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004966 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004967 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004968 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004969 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004970 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004971 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004972 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004973 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004974 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004975 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004976 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004977 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004978 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004979 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004980 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004981 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004982 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004983 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004984 goto error;
4985 }
Radek Krejci73adb602015-07-02 18:07:40 +02004986
Michal Vasko345da0a2015-12-02 10:35:55 +01004987 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004988 }
4989
Michal Vasko508a50d2016-09-07 14:50:33 +02004990 /* check XPath dependencies */
4991 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4992 goto error;
4993 }
4994
Michal Vasko0ea41032015-06-16 08:53:55 +02004995 return retval;
4996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004998
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004999 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005000 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005001 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005002 }
5003
5004 return NULL;
5005}
5006
Michal Vasko0d343d12015-08-24 14:57:36 +02005007/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005008static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005009read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005010 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005011{
Radek Krejcie0674f82015-06-15 13:58:51 +02005012 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005013 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005014 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005015 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005016 int r;
Pavol Vican3cb70c72016-09-05 11:32:52 +02005017 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005018
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005019 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005020 if (module->version < 2) {
Michal Vaskobb174852016-07-25 11:00:21 +02005021 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
5022 return NULL;
5023 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005024 for (node = parent; node; node = lys_parent(node)) {
5025 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
5026 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
5027 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
5028 return NULL;
5029 }
5030 }
5031 }
5032
Radek Krejcie0674f82015-06-15 13:58:51 +02005033 /* init */
5034 memset(&root, 0, sizeof root);
5035
Michal Vasko38d01f72015-06-15 09:41:06 +02005036 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005037 if (!rpc) {
5038 LOGMEM;
5039 return NULL;
5040 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005041 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005042 rpc->prev = (struct lys_node *)rpc;
5043 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005044
Radek Krejci6a113852015-07-03 16:04:20 +02005045 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005046 goto error;
5047 }
5048
Radek Krejcia9544502015-08-14 08:24:29 +02005049 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5050
Radek Krejciadb30652016-07-11 15:27:07 +02005051 /* insert the node into the schema tree */
5052 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5053 goto error;
5054 }
5055
Michal Vasko38d01f72015-06-15 09:41:06 +02005056 /* process rpc's specific children */
5057 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005058 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5059 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005060 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005061 continue;
5062 }
5063
Michal Vasko38d01f72015-06-15 09:41:06 +02005064 if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005065 if (c_input) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005066 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005067 goto error;
5068 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005069 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005070 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005071 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005072 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005073 if (c_output) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005074 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005075 goto error;
5076 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005077 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005078 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005079 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005081 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005082 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005083 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005084 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005086 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005087 } else if (!strcmp(sub->name, "typedef")) {
5088 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005089 } else if (!strcmp(sub->name, "if-feature")) {
5090 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005091 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005092 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005093 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005094 }
5095 }
5096
5097 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5098 if (c_tpdf) {
5099 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005100 if (!rpc->tpdf) {
5101 LOGMEM;
5102 goto error;
5103 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005104 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005105 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005106 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5107 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005108 LOGMEM;
5109 goto error;
5110 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005111 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005112
Radek Krejci73adb602015-07-02 18:07:40 +02005113 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005114 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005115 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5116 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005117 if (r) {
5118 goto error;
5119 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005120 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005121 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
5122 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005123 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005124 goto error;
5125 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005126 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005127 }
5128
5129 /* last part - process data nodes */
5130 LY_TREE_FOR_SAFE(root.child, next, sub) {
5131 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005132 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005133 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005134 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005135 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005136 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005137 goto error;
5138 }
Radek Krejci73adb602015-07-02 18:07:40 +02005139
Michal Vasko345da0a2015-12-02 10:35:55 +01005140 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005141 }
5142
Michal Vasko38d01f72015-06-15 09:41:06 +02005143 return retval;
5144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005145error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005146
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005147 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005148 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005149 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005150 }
5151
5152 return NULL;
5153}
5154
Michal Vasko0d343d12015-08-24 14:57:36 +02005155/* logs directly
5156 *
Radek Krejci74705112015-06-05 10:25:44 +02005157 * resolve - referenced grouping should be bounded to the namespace (resolved)
5158 * only when uses does not appear in grouping. In a case of grouping's uses,
5159 * we just get information but we do not apply augment or refine to it.
5160 */
Radek Krejci76512572015-08-04 09:47:08 +02005161static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005162read_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 +02005163{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005164 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005165 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005166 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005168 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005172 if (!uses) {
5173 LOGMEM;
5174 return NULL;
5175 }
Radek Krejci76512572015-08-04 09:47:08 +02005176 uses->nodetype = LYS_USES;
5177 uses->prev = (struct lys_node *)uses;
5178 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005179
Radek Krejcia9544502015-08-14 08:24:29 +02005180 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005182
Michal Vaskoe0c59842015-09-24 13:52:20 +02005183 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02005184 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 goto error;
5186 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005187
Radek Krejcia9544502015-08-14 08:24:29 +02005188 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5189
Radek Krejciadb30652016-07-11 15:27:07 +02005190 /* insert the node into the schema tree */
5191 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5192 goto error;
5193 }
5194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005195 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005196 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005197 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5198 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005199 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005200 continue;
5201 }
5202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005203 if (!strcmp(sub->name, "refine")) {
5204 c_ref++;
5205 } else if (!strcmp(sub->name, "augment")) {
5206 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005207 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005208 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005209 } else if (!strcmp(sub->name, "when")) {
5210 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005211 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005212 goto error;
5213 }
5214
5215 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005216 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005217 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005218 goto error;
5219 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005220 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005221 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005222 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005224 }
5225 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005227 /* process properties with cardinality 0..n */
5228 if (c_ref) {
5229 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005230 if (!uses->refine) {
5231 LOGMEM;
5232 goto error;
5233 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005234 }
5235 if (c_aug) {
5236 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005237 if (!uses->augment) {
5238 LOGMEM;
5239 goto error;
5240 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005241 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005242 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005243 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5244 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005245 LOGMEM;
5246 goto error;
5247 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005248 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005249
Radek Krejcia9544502015-08-14 08:24:29 +02005250 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005251 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005252 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005253 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005254 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005255 goto error;
5256 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005257 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005258 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5259 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005260 if (r) {
5261 goto error;
5262 }
5263 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005264 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
5265 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005266 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005267 goto error;
5268 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 }
5270 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005271
Radek Krejci48464ed2016-03-17 15:44:09 +01005272 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005273 goto error;
5274 }
Radek Krejci74705112015-06-05 10:25:44 +02005275
Michal Vasko508a50d2016-09-07 14:50:33 +02005276 /* check XPath dependencies */
5277 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5278 goto error;
5279 }
5280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005282
5283error:
5284
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005285 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005287 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005288}
5289
Michal Vasko0d343d12015-08-24 14:57:36 +02005290/* logs directly
5291 *
5292 * common code for yin_read_module() and yin_read_submodule()
5293 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005294static int
Radek Krejcic071c542016-01-27 14:57:51 +01005295read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5296 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005297{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005299 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005300 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005301 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005302 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005303 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005304 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005305 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005306 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005307 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02005308 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 +02005309
Radek Krejcic071c542016-01-27 14:57:51 +01005310 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005311 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 /* init */
5314 memset(&root, 0, sizeof root);
5315 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005316 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02005317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 /*
5319 * in the first run, we process elements with cardinality of 1 or 0..1 and
5320 * count elements with cardinality 0..n. Data elements (choices, containers,
5321 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5322 * need have all top-level and groupings already prepared at that time. In
5323 * the middle loop, we process other elements with carinality of 0..n since
5324 * we need to allocate arrays to store them.
5325 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005326 LY_TREE_FOR_SAFE(yin->child, next, child) {
5327 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005328 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005329 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005330 continue;
5331 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005332
Radek Krejcic071c542016-01-27 14:57:51 +01005333 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005335 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005336 goto error;
5337 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005338 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005339 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005340 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005341 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005343 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 goto error;
5345 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005346 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005347 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005348 goto error;
5349 }
5350 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005351 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005352 } else if (submodule && !strcmp(child->name, "belongs-to")) {
5353 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005354 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 goto error;
5356 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005357 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005358 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005359 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 goto error;
5361 }
Radek Krejcif3886932015-06-04 17:36:06 +02005362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005363 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005364 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005365 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005366 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005367 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005368 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005370 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005371 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005372 goto error;
5373 }
5374 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005375 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005376 /* check here differs from a generic prefix check, since this prefix
5377 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005378 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005379 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005380 goto error;
5381 }
Radek Krejcic071c542016-01-27 14:57:51 +01005382 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005384 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005385 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005386
5387 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005388 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005389 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005390 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005391 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005392 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005393 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005394 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005395 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005396 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005398 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005399 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005400 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005401 lyxml_unlink_elem(ctx, child, 2);
5402 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005403
Radek Krejci1d82ef62015-08-07 14:44:40 +02005404 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005405 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005406 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02005407 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005409 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005410 } else if (!strcmp(child->name, "container") ||
5411 !strcmp(child->name, "leaf-list") ||
5412 !strcmp(child->name, "leaf") ||
5413 !strcmp(child->name, "list") ||
5414 !strcmp(child->name, "choice") ||
5415 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005416 !strcmp(child->name, "anyxml") ||
5417 !strcmp(child->name, "rpc") ||
5418 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005419 lyxml_unlink_elem(ctx, child, 2);
5420 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005421
Radek Krejci1d82ef62015-08-07 14:44:40 +02005422 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005423 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005424 lyxml_unlink_elem(ctx, child, 2);
5425 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005428 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005429 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005430 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005431 goto error;
5432 }
Radek Krejcic071c542016-01-27 14:57:51 +01005433 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005434 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005435 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 goto error;
5437 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005438 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005439 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005440 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005441 goto error;
5442 }
Radek Krejcic071c542016-01-27 14:57:51 +01005443 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005444 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005445 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005446 goto error;
5447 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005448 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005449 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005450 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005451 goto error;
5452 }
Radek Krejcic071c542016-01-27 14:57:51 +01005453 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005454 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005455 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005456 goto error;
5457 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005458 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005459 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005460 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005461 goto error;
5462 }
Radek Krejcic071c542016-01-27 14:57:51 +01005463 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005464 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005465 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005466 goto error;
5467 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005468 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005469 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005470 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005471 goto error;
5472 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005473 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005474 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005475 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 goto error;
5477 }
Radek Krejcic071c542016-01-27 14:57:51 +01005478 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005479 if (!strcmp(value, "1")) {
5480 if (submodule) {
5481 if (module->version > 1) {
5482 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5483 goto error;
5484 }
5485 } else {
5486 module->version = 1;
5487 }
5488 } else {
5489 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005490 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005491 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5492 goto error;
5493 }
5494 } else {
5495 module->version = 2;
5496 }
5497 }
5498
Michal Vasko345da0a2015-12-02 10:35:55 +01005499 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005500
Radek Krejci1d82ef62015-08-07 14:44:40 +02005501 } else if (!strcmp(child->name, "extension")) {
5502 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005503
Radek Krejci3d468122015-10-02 13:36:12 +02005504 /* we have the following supported (hardcoded) extensions: */
5505 /* ietf-netconf's get-filter-element-attributes */
5506 if (!strcmp(module->ns, LY_NSNC) &&
5507 !strcmp(value, "get-filter-element-attributes")) {
5508 LOGDBG("NETCONF filter extension found");
5509 /* NACM's default-deny-write and default-deny-all */
5510 } else if (!strcmp(module->ns, LY_NSNACM) &&
5511 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5512 LOGDBG("NACM extension found");
5513 /* other extensions are not supported, so inform about such an extension */
5514 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005515 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005516 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005517 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005518 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005519 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005520 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005521 }
5522 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005523
Radek Krejcic071c542016-01-27 14:57:51 +01005524 /* check for mandatory statements */
5525 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005526 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005527 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005528 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005530 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005531 goto error;
5532 }
5533 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005534 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005535 goto error;
5536 }
5537 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005539 /* allocate arrays for elements with cardinality of 0..n */
5540 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005541 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5542 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005543 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005544 LOGMEM;
5545 goto error;
5546 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005547 /* set stop block for possible realloc */
5548 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005549 }
5550 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005551 trg->rev = calloc(c_rev, sizeof *trg->rev);
5552 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005553 LOGMEM;
5554 goto error;
5555 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005556 }
5557 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005558 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5559 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005560 LOGMEM;
5561 goto error;
5562 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005563 }
5564 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005565 trg->ident = calloc(c_ident, sizeof *trg->ident);
5566 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005567 LOGMEM;
5568 goto error;
5569 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005570 }
5571 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005572 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5573 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005574 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005575 LOGMEM;
5576 goto error;
5577 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005578 /* set stop block for possible realloc */
5579 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005580 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005581 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005582 trg->augment = calloc(c_aug, sizeof *trg->augment);
5583 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005584 LOGMEM;
5585 goto error;
5586 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005587 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005588 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005589 trg->features = calloc(c_ftrs, sizeof *trg->features);
5590 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005591 LOGMEM;
5592 goto error;
5593 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005594 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005595 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005596 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5597 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005598 LOGMEM;
5599 goto error;
5600 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005601 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005602
Michal Vasko2f7925f2015-10-21 15:06:56 +02005603 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5604 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005605 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005606 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5607 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005608 if (r) {
5609 goto error;
5610 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005611
Radek Krejci1d82ef62015-08-07 14:44:40 +02005612 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005613 memset(&inc, 0, sizeof inc);
5614 /* 1) pass module, not trg, since we want to pass the main module
5615 * 2) we cannot pass directly the structure in the array since
5616 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01005617 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005618 if (!r) {
5619 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02005620 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
5621 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005622 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005623 goto error;
5624 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005625
Radek Krejci1d82ef62015-08-07 14:44:40 +02005626 } else if (!strcmp(child->name, "revision")) {
5627 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005628 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005629 goto error;
5630 }
Radek Krejcic071c542016-01-27 14:57:51 +01005631 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005632 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005633 for (i = 0; i < trg->rev_size; i++) {
5634 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005635 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5636 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005637 }
5638 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005639
Radek Krejci1d82ef62015-08-07 14:44:40 +02005640 LY_TREE_FOR(child->child, child2) {
5641 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005642 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005643 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005644 goto error;
5645 }
Radek Krejcic071c542016-01-27 14:57:51 +01005646 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5647 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005648 goto error;
5649 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005650 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005651 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005653 goto error;
5654 }
Radek Krejcic071c542016-01-27 14:57:51 +01005655 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5656 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005657 goto error;
5658 }
5659 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005660 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005661 goto error;
5662 }
5663 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005665 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005666 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005667 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005668 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005669 if (!value) {
5670 LOGMEM;
5671 goto error;
5672 }
Radek Krejcic071c542016-01-27 14:57:51 +01005673 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5674 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005675 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005676
Radek Krejci749190d2016-02-18 16:26:25 +01005677 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005678 value = trg->rev[0].dsc;
5679 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5680 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005681 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005682
Radek Krejci749190d2016-02-18 16:26:25 +01005683 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005684 value = trg->rev[0].ref;
5685 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5686 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005687 }
5688 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005689
Radek Krejcic071c542016-01-27 14:57:51 +01005690 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005691
Radek Krejci1d82ef62015-08-07 14:44:40 +02005692 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005693 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5694 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005695 if (r) {
5696 goto error;
5697 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005698
Radek Krejci1d82ef62015-08-07 14:44:40 +02005699 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005700 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5701 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 if (r) {
5703 goto error;
5704 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005705
Radek Krejci1d82ef62015-08-07 14:44:40 +02005706 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005707 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5708 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005709 if (r) {
5710 goto error;
5711 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005712
Radek Krejci1d82ef62015-08-07 14:44:40 +02005713 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005714 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5715 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005716 if (r) {
5717 goto error;
5718 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005719 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005720 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005721
Radek Krejcib8f98c12016-06-24 10:30:46 +02005722 if (!submodule) {
5723 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005724 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005725 if (module->inc_size) {
5726 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5727 if (!module->inc) {
5728 LOGMEM;
5729 goto error;
5730 }
5731 }
5732 if (module->imp_size) {
5733 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5734 if (!module->imp) {
5735 LOGMEM;
5736 goto error;
5737 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005738 }
5739 }
Radek Krejcic071c542016-01-27 14:57:51 +01005740
Radek Krejcif5be10f2015-06-16 13:29:36 +02005741 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005742 * refer to them. Submodule's data nodes are stored in the
5743 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005744 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005745 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005746 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005747 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005748 goto error;
5749 }
Radek Krejci74705112015-06-05 10:25:44 +02005750
Michal Vasko345da0a2015-12-02 10:35:55 +01005751 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005752 }
Radek Krejci74705112015-06-05 10:25:44 +02005753
Radek Krejcif5be10f2015-06-16 13:29:36 +02005754 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005755 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005756
Radek Krejci1d82ef62015-08-07 14:44:40 +02005757 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005758 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005759 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005760 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005761 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005762 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005763 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005764 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005765 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005766 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005767 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005768 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005769 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02005770 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
5771 } else if (!strcmp(child->name, "anydata")) {
5772 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005773 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005774 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005775 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005776 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005777 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005778 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005779 goto error;
5780 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005781
Michal Vasko345da0a2015-12-02 10:35:55 +01005782 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005783 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005784
Michal Vasko2f7925f2015-10-21 15:06:56 +02005785 /* ... and finally augments (last, so we can augment our data, for instance) */
5786 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005787 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5788 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005789
Michal Vasko2f7925f2015-10-21 15:06:56 +02005790 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005791 goto error;
5792 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005793 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005794 }
5795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005796 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005797
5798error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005799 /* cleanup */
5800 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005801 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005802 }
5803 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005804 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005805 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005806 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005807 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005808 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005810 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005811}
5812
Michal Vasko0d343d12015-08-24 14:57:36 +02005813/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005814struct lys_submodule *
5815yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005816{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005817 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005818 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005819 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005820
Michal Vasko5a721fd2016-02-16 12:16:48 +01005821 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005822
Radek Krejci722b0072016-02-01 17:09:45 +01005823 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005824 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005825 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005826 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005828 /* check root element */
5829 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005830 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005831 goto error;
5832 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005834 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005835 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005836 goto error;
5837 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005838
Michal Vasko5a721fd2016-02-16 12:16:48 +01005839 submodule = calloc(1, sizeof *submodule);
5840 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005841 LOGMEM;
5842 goto error;
5843 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005844
Michal Vasko5a721fd2016-02-16 12:16:48 +01005845 submodule->ctx = module->ctx;
5846 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5847 submodule->type = 1;
5848 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005849
Michal Vasko5a721fd2016-02-16 12:16:48 +01005850 LOGVRB("Reading submodule \"%s\".", submodule->name);
5851 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005852 goto error;
5853 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005855 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005856 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005857
Michal Vasko5a721fd2016-02-16 12:16:48 +01005858 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005859 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005860
5861error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005862 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005863 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005864 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005865
Michal Vasko5a721fd2016-02-16 12:16:48 +01005866 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005867 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005868 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005869 }
5870
Michal Vasko5a721fd2016-02-16 12:16:48 +01005871 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005872
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005873 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5874 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005875 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005876 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005877}
5878
Michal Vasko0d343d12015-08-24 14:57:36 +02005879/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005880struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005881yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005882{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005883 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005884 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005885 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005886 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005887
Radek Krejcic071c542016-01-27 14:57:51 +01005888 unres = calloc(1, sizeof *unres);
5889 if (!unres) {
5890 LOGMEM;
5891 return NULL;
5892 }
5893
Radek Krejci722b0072016-02-01 17:09:45 +01005894 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005895 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005896 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005897 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005899 /* check root element */
5900 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005901 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005902 goto error;
5903 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005905 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005906 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005907 goto error;
5908 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005910 module = calloc(1, sizeof *module);
5911 if (!module) {
5912 LOGMEM;
5913 goto error;
5914 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005916 module->ctx = ctx;
5917 module->name = lydict_insert(ctx, value, strlen(value));
5918 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005919 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005920
Michal Vasko9f258e42016-02-11 11:36:27 +01005921 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005922 if (read_sub_module(module, NULL, yin, unres)) {
5923 goto error;
5924 }
5925
5926 /* resolve rest of unres items */
5927 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005928 goto error;
5929 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005930
Radek Krejciff4874d2016-03-07 12:30:50 +01005931 if (revision) {
5932 /* check revision of the parsed model */
5933 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005934 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5935 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005936 goto error;
5937 }
5938 }
5939
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005940 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005941 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005942 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005943
Radek Krejci27fe55e2016-09-13 17:13:35 +02005944 if (module->deviation_size && !module->implemented) {
5945 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
5946 /* deviations always causes target to be made implemented,
5947 * but augents and leafrefs not, so we have to apply them now */
5948 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02005949 goto error;
5950 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005951 }
5952
Michal Vasko345da0a2015-12-02 10:35:55 +01005953 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005954 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005955 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005956 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005957
5958error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005959 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005960 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005961 unres_schema_free(module, &unres);
5962
5963 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005964 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005965 return NULL;
5966 }
5967
5968 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005969
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005970 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005971 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005972 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005973}