blob: e8d9bf55fe8d5c2ccb6c5fbcd78756eb22834d01 [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
Michal Vaskoe022a562016-09-27 14:24:15 +020042#define OPT_IDENT 0x01
43#define OPT_CFG_PARSE 0x02
44#define OPT_CFG_INHERIT 0x04
45#define OPT_CFG_IGNORE 0x08
46#define OPT_MODULE 0x10
47#define OPT_NACMEXT 0x20
Radek Krejcib8048692015-08-05 13:36:34 +020048static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020049
Radek Krejcib8048692015-08-05 13:36:34 +020050static 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 +020051 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020052static 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 +020053 int valid_config, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020054static 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 +020055 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static 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 +020057 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static 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 +020059 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static 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 +020061 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static 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 +020063 int valid_config, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020064static 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 +020065 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020066static 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 +020067 int valid_config, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020068static 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 +020069 struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020070static 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 +020071 struct unres_schema *unres);
Michal Vaskof02e3742015-08-05 16:27:02 +020072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020073
Michal Vasko0d343d12015-08-24 14:57:36 +020074/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020075static const char *
76read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020077{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020078 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020080 /* there should be <text> child */
81 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010082 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010083 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010084 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020085 } else if (node->child->content) {
86 len = strlen(node->child->content);
87 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010088 } else {
89 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020090 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020091}
92
Michal Vasko0d343d12015-08-24 14:57:36 +020093/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020094static int
Radek Krejci9de2c042016-10-19 16:53:06 +020095fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
96 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +010097{
98 int r;
99 const char *value;
100
101 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200102
103 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
104 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200105error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100106 return EXIT_FAILURE;
107 }
108
Michal Vasko56d082c2016-10-25 14:00:42 +0200109 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100110 return EXIT_FAILURE;
111 }
112
Radek Krejci9de2c042016-10-19 16:53:06 +0200113 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100114 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200115 if (r) {
116 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100117 }
118
Radek Krejci9ff0a922016-07-14 13:08:05 +0200119 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100120}
121
122/* logs directly */
123static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200124fill_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 +0200125{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200126 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200127 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200128 int rc;
129 int c_ftrs = 0, c_base = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200130
Michal Vasko4cfcd252015-08-03 14:31:10 +0200131 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100132 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200133
Radek Krejci76512572015-08-04 09:47:08 +0200134 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200135 return EXIT_FAILURE;
136 }
Radek Krejci04581c62015-05-22 21:24:00 +0200137
Pavol Vicand6cda452016-07-13 15:08:29 +0200138 if (dup_identities_check(ident->name, module)) {
139 return EXIT_FAILURE;
140 }
141
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200142 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200143 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
144 /* garbage */
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200145 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200146 continue;
147 }
148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200149 if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200150 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100151 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200152 return EXIT_FAILURE;
153 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200154 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100155
Radek Krejci018f1f52016-08-03 16:01:20 +0200156 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
157 c_ftrs++;
158
159 } else {
160 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
161 return EXIT_FAILURE;
162 }
163 }
164
165 if (c_base) {
166 ident->base_size = 0;
167 ident->base = calloc(c_base, sizeof *ident->base);
168 if (!ident->base) {
169 LOGMEM;
170 return EXIT_FAILURE;
171 }
172 }
173
174 if (c_ftrs) {
175 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
176 if (!ident->iffeature) {
177 LOGMEM;
178 return EXIT_FAILURE;
179 }
180 }
181
182 LY_TREE_FOR(yin->child, node) {
183 if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200184 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100185 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100186 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200187 return EXIT_FAILURE;
188 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100189
Radek Krejci48464ed2016-03-17 15:44:09 +0100190 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100191 lydict_remove(module->ctx, value);
192 return EXIT_FAILURE;
193 }
194 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200195 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200196 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200197 ident->iffeature_size++;
198 if (rc) {
199 return EXIT_FAILURE;
200 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200201 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200202 }
Radek Krejci04581c62015-05-22 21:24:00 +0200203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200204 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200205
206error:
207 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200208}
209
Michal Vasko0d343d12015-08-24 14:57:36 +0200210/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200211static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200212read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200213{
Radek Krejci73adb602015-07-02 18:07:40 +0200214 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200215 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200216
Radek Krejci73adb602015-07-02 18:07:40 +0200217 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200218 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
219 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200220 continue;
221 }
222
Radek Krejci41726f92015-06-19 13:11:05 +0200223 if (!strcmp(child->name, "description")) {
224 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100225 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200226 return EXIT_FAILURE;
227 }
228 restr->dsc = read_yin_subnode(ctx, child, "text");
229 if (!restr->dsc) {
230 return EXIT_FAILURE;
231 }
232 } else if (!strcmp(child->name, "reference")) {
233 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100234 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200235 return EXIT_FAILURE;
236 }
237 restr->ref = read_yin_subnode(ctx, child, "text");
238 if (!restr->ref) {
239 return EXIT_FAILURE;
240 }
241 } else if (!strcmp(child->name, "error-app-tag")) {
242 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100243 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200244 return EXIT_FAILURE;
245 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200246 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200247 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200248 } else if (!strcmp(child->name, "error-message")) {
249 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100250 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200251 return EXIT_FAILURE;
252 }
253 restr->emsg = read_yin_subnode(ctx, child, "value");
254 if (!restr->emsg) {
255 return EXIT_FAILURE;
256 }
257 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100258 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200259 return EXIT_FAILURE;
260 }
Radek Krejci41726f92015-06-19 13:11:05 +0200261 }
262
263 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200264
265error:
266 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200267}
268
Michal Vasko88c29542015-11-27 14:57:53 +0100269/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
270int
Radek Krejcib8048692015-08-05 13:36:34 +0200271fill_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 +0200272 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200273{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200274 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200275 struct lys_node *siter;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200276 struct lyxml_elem *next, *next2, *node, *child;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200277 struct lys_restr **restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200278 struct lys_type_bit bit, *bits_sc = NULL;
279 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200280 struct lys_type *dertype;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200281 int i, j, rc, val_set, c_ftrs;
Radek Krejcidc008d72016-02-17 13:12:14 +0100282 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200283 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200284 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200285 size_t len;
286 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200287
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200288 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100289 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200290 if (!value) {
291 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200292 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200293
294 i = parse_identifier(value);
295 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100296 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100297 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200298 goto error;
299 }
300 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100301 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200302 if (value[i]) {
303 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100304 name += i;
305 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100306 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100307 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200308 goto error;
309 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200310 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100311 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200312 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200313
Radek Krejci225376f2016-02-16 17:36:22 +0100314 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200315 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100316 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200317 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200318 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100319
320 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200321 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200322 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200323 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100324 ret = EXIT_FAILURE;
325 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200326 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200327 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200328
Radek Krejci9b6aad22016-09-20 15:55:51 +0200329 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200330 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200331 * 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 +0200332 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
333 if (siter) {
334 if (!((struct lys_node_grp *)siter)->nacm) {
335 LOGINT;
336 goto error;
337 }
338 ((struct lys_node_grp *)siter)->nacm--;
339 } else {
340 LOGINT;
341 goto error;
342 }
343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200344 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200345
Radek Krejcicf509982015-12-15 09:22:44 +0100346 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100347 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100348 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100349 return -1;
350 }
351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200352 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200354 /* RFC 6020 9.7.4 - bit */
355
356 /* get bit specifications, at least one must be present */
357 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200358 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
359 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100360 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200361 continue;
362 }
363
Radek Krejci994b6f62015-06-18 16:47:27 +0200364 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200365 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200366 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100367 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200368 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200369 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200370 }
371 }
Radek Krejcie663e012016-08-01 17:12:34 +0200372 dertype = &type->der->type;
373 if (!dertype->der) {
374 if (!type->info.bits.count) {
375 /* type is derived directly from buit-in bits type and bit statement is required */
376 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
377 goto error;
378 }
379 } else {
380 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
381 if (module->version < 2 && type->info.bits.count) {
382 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
383 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
384 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200385 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200386 goto error;
387 }
Radek Krejciac781922015-07-09 15:35:14 +0200388 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200389
390 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100391 if (!type->info.bits.bit) {
392 LOGMEM;
393 goto error;
394 }
Radek Krejci73adb602015-07-02 18:07:40 +0200395 p = 0;
396 i = -1;
397 LY_TREE_FOR(yin->child, next) {
398 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200399 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200400
401 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100402 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100403 goto error;
404 }
405
Radek Krejci994b6f62015-06-18 16:47:27 +0200406 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200407 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200408 type->info.bits.count = i + 1;
409 goto error;
410 }
411
Radek Krejcie663e012016-08-01 17:12:34 +0200412 if (!dertype->der) { /* directly derived type from bits built-in type */
413 /* check the name uniqueness */
414 for (j = 0; j < i; j++) {
415 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
416 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
417 type->info.bits.count = i + 1;
418 goto error;
419 }
420 }
421 } else {
422 /* restricted bits type - the name MUST be used in the base type */
423 bits_sc = dertype->info.bits.bit;
424 for (j = 0; j < dertype->info.bits.count; j++) {
425 if (ly_strequal(bits_sc[j].name, value, 1)) {
426 break;
427 }
428 }
429 if (j == dertype->info.bits.count) {
430 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200431 type->info.bits.count = i + 1;
432 goto error;
433 }
434 }
435
Radek Krejcie663e012016-08-01 17:12:34 +0200436
Radek Krejci0d70c372015-07-02 16:23:10 +0200437 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200438 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200439 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
440 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200441 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200442 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200443
Radek Krejci0d70c372015-07-02 16:23:10 +0200444 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200445 if (p_ != -1) {
446 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
447 type->info.bits.count = i + 1;
448 goto error;
449 }
450
Radek Krejci0d70c372015-07-02 16:23:10 +0200451 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200452 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200453
454 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200455 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100456 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200457 type->info.bits.count = i + 1;
458 goto error;
459 }
460 type->info.bits.bit[i].pos = (uint32_t)p_;
461
Radek Krejcie663e012016-08-01 17:12:34 +0200462 if (!dertype->der) { /* directly derived type from bits built-in type */
463 /* keep the highest enum value for automatic increment */
464 if (type->info.bits.bit[i].pos >= p) {
465 p = type->info.bits.bit[i].pos;
466 p++;
467 } else {
468 /* check that the value is unique */
469 for (j = 0; j < i; j++) {
470 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
471 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
472 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
473 type->info.bits.bit[j].name);
474 type->info.bits.count = i + 1;
475 goto error;
476 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200477 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200478 }
479 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200480
481 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
482 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200483 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100484 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200485 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200486 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200487 }
Radek Krejcie663e012016-08-01 17:12:34 +0200488
489 if (!dertype->der) { /* directly derived type from bits built-in type */
490 if (p_ == -1) {
491 /* assign value automatically */
492 if (p > UINT32_MAX) {
493 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
494 type->info.bits.count = i + 1;
495 goto error;
496 }
497 type->info.bits.bit[i].pos = (uint32_t)p;
498 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
499 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200500 }
Radek Krejcie663e012016-08-01 17:12:34 +0200501 } else { /* restricted bits type */
502 if (p_ == -1) {
503 /* automatically assign position from base type */
504 type->info.bits.bit[i].pos = bits_sc[j].pos;
505 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
506 } else {
507 /* check that the assigned position corresponds to the original
508 * position of the bit in the base type */
509 if (p_ != bits_sc[j].pos) {
510 /* p_ - assigned position in restricted bits
511 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
512 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200513 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200514 type->info.bits.count = i + 1;
515 goto error;
516 }
517 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200518 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200519
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200520 /* if-features */
521 if (c_ftrs) {
522 bits_sc = &type->info.bits.bit[i];
523 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
524 if (!bits_sc->iffeature) {
525 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200526 type->info.bits.count = i + 1;
527 goto error;
528 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200529
530 LY_TREE_FOR(next->child, node) {
531 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200532 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200533 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
534 bits_sc->iffeature_size++;
535 if (rc) {
536 type->info.bits.count = i + 1;
537 goto error;
538 }
539 }
540 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200541 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200542
543 /* keep them ordered by position */
544 j = i;
545 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
546 /* switch them */
547 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
548 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
549 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
550 j--;
551 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200552 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200553 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200555 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200556 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200557 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200558 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
559 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200560 continue;
561 }
562
Radek Krejcif9401c32015-06-26 16:47:36 +0200563 if (!strcmp(node->name, "range")) {
564 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200566 goto error;
567 }
568
569 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200570 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100571 if (!type->info.dec64.range) {
572 LOGMEM;
573 goto error;
574 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200575 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
576
577 /* get possible substatements */
578 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
579 goto error;
580 }
581 } else if (!strcmp(node->name, "fraction-digits")) {
582 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100583 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200584 goto error;
585 }
586 GETVAL(value, node, "value");
587 v = strtol(value, NULL, 10);
588
589 /* range check */
590 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100591 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200592 goto error;
593 }
594 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200595 type->info.dec64.div = 10;
596 for (i = 1; i < v; i++) {
597 type->info.dec64.div *= 10;
598 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200599 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100600 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200601 goto error;
602 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200603 }
604
605 /* mandatory sub-statement(s) check */
606 if (!type->info.dec64.dig && !type->der->type.der) {
607 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100608 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200609 goto error;
610 }
Radek Krejci7511f402015-07-10 09:56:30 +0200611 if (type->info.dec64.dig && type->der->type.der) {
612 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100613 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200614 goto error;
615 }
Radek Krejci4800f652016-09-08 14:02:52 +0200616
617 /* copy fraction-digits specification from parent type for easier internal use */
618 if (type->der->type.der) {
619 type->info.dec64.dig = type->der->type.info.dec64.dig;
620 type->info.dec64.div = type->der->type.info.dec64.div;
621 }
622
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200623 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
624 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
625 goto error;
626 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200627 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200630 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200631
Radek Krejci994b6f62015-06-18 16:47:27 +0200632 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200633 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200634 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
635 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100636 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200637 continue;
638 }
639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200642 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100643 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200644 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200645 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200646 }
647 }
Radek Krejcie663e012016-08-01 17:12:34 +0200648 dertype = &type->der->type;
649 if (!dertype->der) {
650 if (!type->info.enums.count) {
651 /* type is derived directly from buit-in enumeartion type and enum statement is required */
652 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
653 goto error;
654 }
655 } else {
656 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
657 if (module->version < 2 && type->info.enums.count) {
658 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
659 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
660 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200661 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200662 goto error;
663 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200664 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200665
Radek Krejci1574a8d2015-08-03 14:16:52 +0200666 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100667 if (!type->info.enums.enm) {
668 LOGMEM;
669 goto error;
670 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200671
Radek Krejcie663e012016-08-01 17:12:34 +0200672 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200673 i = -1;
674 LY_TREE_FOR(yin->child, next) {
675 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200676 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200677
678 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100679 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100680 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
681 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100682 goto error;
683 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200684 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200685 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200686 type->info.enums.count = i + 1;
687 goto error;
688 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200690 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200691 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200692 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100693 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 type->info.enums.count = i + 1;
695 goto error;
696 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200697
Radek Krejcie663e012016-08-01 17:12:34 +0200698 if (!dertype->der) { /* directly derived type from enumeration built-in type */
699 /* check the name uniqueness */
700 for (j = 0; j < i; j++) {
701 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
702 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
703 type->info.enums.count = i + 1;
704 goto error;
705 }
706 }
707 } else {
708 /* restricted enumeration type - the name MUST be used in the base type */
709 enms_sc = dertype->info.enums.enm;
710 for (j = 0; j < dertype->info.enums.count; j++) {
711 if (ly_strequal(enms_sc[j].name, value, 1)) {
712 break;
713 }
714 }
715 if (j == dertype->info.enums.count) {
716 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 type->info.enums.count = i + 1;
718 goto error;
719 }
720 }
Radek Krejci04581c62015-05-22 21:24:00 +0200721
Radek Krejcie663e012016-08-01 17:12:34 +0200722 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200723 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200724 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
725 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200726 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200728
Radek Krejci0d70c372015-07-02 16:23:10 +0200729 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200730 if (val_set) {
731 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
732 type->info.enums.count = i + 1;
733 goto error;
734 }
735
Radek Krejci0d70c372015-07-02 16:23:10 +0200736 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200737 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200738
739 /* range check */
740 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100741 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200742 type->info.enums.count = i + 1;
743 goto error;
744 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200745 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200746
Radek Krejcie663e012016-08-01 17:12:34 +0200747 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200748 if (!i) {
749 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200750 v = type->info.enums.enm[i].value;
751 v++;
752 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200753 /* keep the highest enum value for automatic increment */
754 if (type->info.enums.enm[i].value >= v) {
755 v = type->info.enums.enm[i].value;
756 v++;
757 } else {
758 /* check that the value is unique */
759 for (j = 0; j < i; j++) {
760 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
761 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
762 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
763 type->info.enums.enm[j].name);
764 type->info.enums.count = i + 1;
765 goto error;
766 }
Radek Krejcie663e012016-08-01 17:12:34 +0200767 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200768 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200769 }
770 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200771 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200772
773 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
774 c_ftrs++;
775
Radek Krejci0d70c372015-07-02 16:23:10 +0200776 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100777 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200778 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200780 }
Radek Krejcie663e012016-08-01 17:12:34 +0200781
782 if (!dertype->der) { /* directly derived type from enumeration */
783 if (!val_set) {
784 /* assign value automatically */
785 if (v > INT32_MAX) {
786 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
787 type->info.enums.count = i + 1;
788 goto error;
789 }
790 type->info.enums.enm[i].value = v;
791 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
792 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200793 }
Radek Krejcie663e012016-08-01 17:12:34 +0200794 } else { /* restricted enum type */
795 if (!val_set) {
796 /* automatically assign value from base type */
797 type->info.enums.enm[i].value = enms_sc[j].value;
798 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
799 } else {
800 /* check that the assigned value corresponds to the original
801 * value of the enum in the base type */
802 if (v_ != enms_sc[j].value) {
803 /* v_ - assigned value in restricted enum
804 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
805 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +0200806 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +0200807 type->info.enums.count = i + 1;
808 goto error;
809 }
810 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200812
813 /* if-features */
814 if (c_ftrs) {
815 enms_sc = &type->info.enums.enm[i];
816 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
817 if (!enms_sc->iffeature) {
818 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200819 type->info.enums.count = i + 1;
820 goto error;
821 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200822
823 LY_TREE_FOR(next->child, node) {
824 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200825 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200826 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
827 enms_sc->iffeature_size++;
828 if (rc) {
829 type->info.enums.count = i + 1;
830 goto error;
831 }
832 }
833 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200834 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200836 }
837 break;
838
839 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200840 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841
Michal Vaskof2d43962016-09-02 11:10:16 +0200842 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200843 LY_TREE_FOR_SAFE(yin->child, next, node) {
844 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
845 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100846 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200847 continue;
848 }
849
Michal Vaskoe29c6622015-11-27 15:02:31 +0100850 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100851 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200852 goto error;
853 }
Michal Vaskof2d43962016-09-02 11:10:16 +0200854
855 GETVAL(value, yin->child, "name");
856 /* store in the JSON format */
857 value = transform_schema2json(module, value);
858 if (!value) {
859 goto error;
860 }
861 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
862 lydict_remove(module->ctx, value);
863
864 if (rc == -1) {
865 goto error;
866 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200867 }
868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200869 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200870 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +0200871 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +0200872 break;
873 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100874 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200875 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +0200876 } else {
877 if (type->der->type.der) {
878 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
879 goto error;
880 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200882 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100883 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 goto error;
885 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 break;
887
888 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200889 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200890 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200891 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
892 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200893 continue;
894 }
895
Radek Krejciaf351422015-06-19 14:49:38 +0200896 if (!strcmp(node->name, "require-instance")) {
897 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100898 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200899 goto error;
900 }
901 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200902 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200903 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200904 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200905 type->info.inst.req = -1;
906 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100907 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200908 goto error;
909 }
910 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100911 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200912 goto error;
913 }
Radek Krejciaf351422015-06-19 14:49:38 +0200914 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916 break;
917
Radek Krejcif2860132015-06-20 12:37:20 +0200918 case LY_TYPE_BINARY:
919 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200920 case LY_TYPE_INT8:
921 case LY_TYPE_INT16:
922 case LY_TYPE_INT32:
923 case LY_TYPE_INT64:
924 case LY_TYPE_UINT8:
925 case LY_TYPE_UINT16:
926 case LY_TYPE_UINT32:
927 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200928 /* RFC 6020 9.2.4 - range */
929
930 /* length and range are actually the same restriction, so process
931 * them by this common code, we just need to differ the name and
932 * structure where the information will be stored
933 */
934 if (type->base == LY_TYPE_BINARY) {
935 restr = &type->info.binary.length;
936 name = "length";
937 } else {
938 restr = &type->info.num.range;
939 name = "range";
940 }
941
Radek Krejci73adb602015-07-02 18:07:40 +0200942 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200943 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
944 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200945 continue;
946 }
947
Radek Krejcif2860132015-06-20 12:37:20 +0200948 if (!strcmp(node->name, name)) {
949 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100950 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200951 goto error;
952 }
953
954 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200955 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100956 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200957 goto error;
958 }
959 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100960 if (!(*restr)) {
961 LOGMEM;
962 goto error;
963 }
Radek Krejcif2860132015-06-20 12:37:20 +0200964 (*restr)->expr = lydict_insert(module->ctx, value, 0);
965
966 /* get possible substatements */
967 if (read_restr_substmt(module->ctx, *restr, node)) {
968 goto error;
969 }
970 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100971 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200972 goto error;
973 }
Radek Krejcif2860132015-06-20 12:37:20 +0200974 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 break;
976
977 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200978 /* flag resolving for later use */
979 if (!tpdftype) {
980 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
981 if (siter) {
982 /* just a flag - do not resolve */
983 tpdftype = 1;
984 }
985 }
986
Radek Krejcidc4c1412015-06-19 15:39:54 +0200987 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200988 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200989 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
990 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 continue;
992 }
993
Michal Vasko88c29542015-11-27 14:57:53 +0100994 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200995 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100996 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200997 goto error;
998 }
999
1000 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001001 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001002 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001003 if (!type->info.lref.path) {
1004 goto error;
1005 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001006
1007 /* try to resolve leafref path only when this is instantiated
1008 * leaf, so it is not:
1009 * - typedef's type,
1010 * - in grouping definition,
1011 * - just instantiated in a grouping definition,
1012 * because in those cases the nodes referenced in path might not be present
1013 * and it is not a bug. */
1014 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001015 goto error;
1016 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001017 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001018 if (type->info.lref.req) {
1019 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1020 goto error;
1021 }
1022 GETVAL(value, node, "value");
1023 if (!strcmp(value, "true")) {
1024 type->info.lref.req = 1;
1025 } else if (!strcmp(value, "false")) {
1026 type->info.lref.req = -1;
1027 } else {
1028 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1029 goto error;
1030 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001031 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001032 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001033 goto error;
1034 }
Radek Krejci73adb602015-07-02 18:07:40 +02001035 }
1036
Radek Krejci742be352016-07-17 12:18:54 +02001037 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001038 if (!type->der->type.der) {
1039 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1040 goto error;
1041 } else {
1042 /* copy leafref definition into the derived type */
1043 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1044 /* and resolve the path at the place we are (if not in grouping/typedef) */
1045 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1046 goto error;
1047 }
1048
1049 /* add pointer to leafref target, only on leaves (not in typedefs) */
1050 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1051 goto error;
1052 }
1053 }
Radek Krejci742be352016-07-17 12:18:54 +02001054 }
1055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001056 break;
1057
1058 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001059 /* RFC 6020 9.4.4 - length */
1060 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001061 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001062 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001063 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1064 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001065 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001066 continue;
1067 }
1068
Radek Krejci3733a802015-06-19 13:43:21 +02001069 if (!strcmp(node->name, "length")) {
1070 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001071 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001072 goto error;
1073 }
1074
1075 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001076 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001077 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001078 goto error;
1079 }
1080 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001081 if (!type->info.str.length) {
1082 LOGMEM;
1083 goto error;
1084 }
Radek Krejci3733a802015-06-19 13:43:21 +02001085 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1086
Radek Krejci5fbc9162015-06-19 14:11:11 +02001087 /* get possible sub-statements */
1088 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001089 goto error;
1090 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001091 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001092 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001093 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001094 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001095 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001096 goto error;
1097 }
1098 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001099 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001100 if (i) {
1101 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001102 if (!type->info.str.patterns) {
1103 LOGMEM;
1104 goto error;
1105 }
Radek Krejci73adb602015-07-02 18:07:40 +02001106 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001107 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001108 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001109 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001110 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001111 goto error;
1112 }
Michal Vasko69068852015-07-13 14:34:31 +02001113
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001114 modifier = 0x06; /* ACK */
1115 name = NULL;
1116 LY_TREE_FOR_SAFE(node->child, next2, child) {
1117 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1118 /* garbage */
1119 lyxml_free(module->ctx, child);
1120 continue;
1121 }
1122
1123 if (module->version >= 2 && !strcmp(child->name, "modifier")) {
1124 if (name) {
1125 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1126 goto error;
1127 }
1128
1129 GETVAL(name, child, "value");
1130 if (!strcmp(name, "invert-match")) {
1131 modifier = 0x15; /* NACK */
1132 } else {
1133 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1134 goto error;
1135 }
1136 lyxml_free(module->ctx, child);
1137 }
1138 }
1139
1140 len = strlen(value);
1141 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1142 buf[0] = modifier;
1143 strcpy(&buf[1], value);
1144
1145 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001146
1147 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +01001148 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +02001149 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001150 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001151 goto error;
1152 }
Radek Krejci73adb602015-07-02 18:07:40 +02001153 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001154 }
1155 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001156 break;
1157
1158 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001159 /* RFC 6020 7.4 - type */
1160 /* count number of types in union */
1161 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001162 LY_TREE_FOR_SAFE(yin->child, next, node) {
1163 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1164 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001165 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001166 continue;
1167 }
1168
Radek Krejcie4c366b2015-07-02 10:11:31 +02001169 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001170 if (type->der->type.der) {
1171 /* type can be a substatement only in "union" type, not in derived types */
1172 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1173 goto error;
1174 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001175 i++;
1176 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001177 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001178 goto error;
1179 }
1180 }
1181
Radek Krejci038d5d92016-09-12 15:07:15 +02001182 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001183 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001184 goto error;
1185 }
1186
1187 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001188 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001189 if (!type->info.uni.types) {
1190 LOGMEM;
1191 goto error;
1192 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001193 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001194 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001195 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001196 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001197 if (!rc) {
1198 type->info.uni.count++;
1199
Radek Krejci7de36cf2016-09-12 16:18:50 +02001200 if (module->version < 2) {
1201 /* union's type cannot be empty or leafref */
1202 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1203 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1204 rc = -1;
1205 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1206 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1207 rc = -1;
1208 }
Michal Vasko88c29542015-11-27 14:57:53 +01001209 }
1210 }
1211 if (rc) {
1212 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1213 for (i = 0; i < type->info.uni.count; ++i) {
1214 lys_type_free(module->ctx, &type->info.uni.types[i]);
1215 }
1216 free(type->info.uni.types);
1217 type->info.uni.types = NULL;
1218 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001219 type->der = NULL;
1220 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001221
1222 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001223 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001224 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001225 goto error;
1226 }
Michal Vasko88c29542015-11-27 14:57:53 +01001227 }
1228 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001229
Michal Vasko88c29542015-11-27 14:57:53 +01001230 case LY_TYPE_BOOL:
1231 case LY_TYPE_EMPTY:
1232 /* no sub-statement allowed */
1233 LY_TREE_FOR(yin->child, node) {
1234 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001235 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001236 goto error;
1237 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001238 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 break;
1240
1241 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001242 LOGINT;
1243 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001244 }
1245
1246 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001247
1248error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001249 if (type->module_name) {
1250 lydict_remove(module->ctx, type->module_name);
1251 type->module_name = NULL;
1252 }
1253 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001254}
1255
Michal Vasko0d343d12015-08-24 14:57:36 +02001256/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001257static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001258fill_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 +02001259{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001261 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +01001262 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001264 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001265 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 goto error;
1267 }
1268 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001270 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001271 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 goto error;
1273 }
Radek Krejcieac35532015-05-31 19:09:15 +02001274
Michal Vasko88c29542015-11-27 14:57:53 +01001275 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001276 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1277 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001278 continue;
1279 }
1280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001281 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001282 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001283 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001284 goto error;
1285 }
Michal Vasko88c29542015-11-27 14:57:53 +01001286 /* HACK for unres */
1287 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001288 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001289 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001290 goto error;
1291 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001292 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001293 } else if (!strcmp(node->name, "default")) {
1294 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001295 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001296 goto error;
1297 }
1298 GETVAL(value, node, "value");
1299 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1300 } else if (!strcmp(node->name, "units")) {
1301 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001302 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001303 goto error;
1304 }
1305 GETVAL(value, node, "name");
1306 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1307 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001308 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001309 goto error;
1310 }
1311 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001313 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001314 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001315 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001316 goto error;
1317 }
Radek Krejcieac35532015-05-31 19:09:15 +02001318
Michal Vasko478c4652016-07-21 12:55:01 +02001319 /* check default value (if not defined, there still could be some restrictions
1320 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01001321 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001322 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001323 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001325 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001326
1327error:
1328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001330}
1331
Michal Vasko0d343d12015-08-24 14:57:36 +02001332/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001333static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001334fill_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 +02001335{
1336 const char *value;
1337 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001338 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001339
Radek Krejcib05774c2015-06-18 13:52:59 +02001340 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001341 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001342 goto error;
1343 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001344 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001345 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001346
Radek Krejci76512572015-08-04 09:47:08 +02001347 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001348 goto error;
1349 }
1350
1351 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001352 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1353 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001354 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001355 continue;
1356 }
1357
Radek Krejci3cf9e222015-06-18 11:37:50 +02001358 if (!strcmp(child->name, "if-feature")) {
1359 c++;
1360 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001361 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001362 goto error;
1363 }
1364 }
1365
1366 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001367 f->iffeature = calloc(c, sizeof *f->iffeature);
1368 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001369 LOGMEM;
1370 goto error;
1371 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001372 }
Radek Krejci73adb602015-07-02 18:07:40 +02001373 LY_TREE_FOR(yin->child, child) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001374 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001375 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001376 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001377 goto error;
1378 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001379 }
1380
Radek Krejcic79c6b12016-07-26 15:11:49 +02001381 /* check for circular dependencies */
1382 if (f->iffeature_size) {
1383 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1384 goto error;
1385 }
1386 }
1387
Radek Krejci3cf9e222015-06-18 11:37:50 +02001388 return EXIT_SUCCESS;
1389
1390error:
1391
1392 return EXIT_FAILURE;
1393}
1394
Michal Vasko0d343d12015-08-24 14:57:36 +02001395/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001396static int
Radek Krejcib8048692015-08-05 13:36:34 +02001397fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001398{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001399 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001401 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001402 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001403 if (!must->expr) {
1404 goto error;
1405 }
Radek Krejci800af702015-06-02 13:46:01 +02001406
Radek Krejci41726f92015-06-19 13:11:05 +02001407 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001408
Michal Vasko77dc5652016-02-15 12:32:42 +01001409error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001410 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001411}
1412
Radek Krejci581ce772015-11-10 17:22:40 +01001413static int
Michal Vasko88c29542015-11-27 14:57:53 +01001414fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1415 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001416{
1417 int i, j;
1418 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001419 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001420
1421 /* get unique value (list of leafs supposed to be unique */
1422 GETVAL(value, yin, "tag");
1423
1424 /* count the number of unique leafs in the value */
1425 vaux = value;
1426 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001427 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001428 while (isspace(*vaux)) {
1429 vaux++;
1430 }
1431 }
1432 unique->expr_size++;
1433 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001434 if (!unique->expr) {
1435 LOGMEM;
1436 goto error;
1437 }
Radek Krejci581ce772015-11-10 17:22:40 +01001438
1439 for (i = 0; i < unique->expr_size; i++) {
1440 vaux = strpbrk(value, " \t\n");
1441 if (!vaux) {
1442 /* the last token, lydict_insert() will count its size on its own */
1443 vaux = value;
1444 }
1445
1446 /* store token into unique structure */
1447 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1448
1449 /* check that the expression does not repeat */
1450 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001451 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001452 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1453 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001454 goto error;
1455 }
1456 }
1457
1458 /* try to resolve leaf */
1459 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001460 unique_info = malloc(sizeof *unique_info);
1461 unique_info->list = parent;
1462 unique_info->expr = unique->expr[i];
1463 unique_info->trg_type = &unique->trg_type;
1464 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001465 goto error;
1466 }
Radek Krejci581ce772015-11-10 17:22:40 +01001467 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001468 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001469 goto error;
1470 }
1471 }
1472
1473 /* move to next token */
1474 value = vaux;
1475 while(isspace(*value)) {
1476 value++;
1477 }
1478 }
1479
1480 return EXIT_SUCCESS;
1481
1482error:
1483 return EXIT_FAILURE;
1484}
1485
Michal Vasko0d343d12015-08-24 14:57:36 +02001486/* logs directly
1487 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001488 * type: 0 - min, 1 - max
1489 */
1490static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001491deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001492{
1493 const char *value;
1494 char *endptr;
1495 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001496 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001497
Michal Vaskof7e57d52016-03-07 11:31:09 +01001498 /* del min/max is forbidden */
1499 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001500 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001501 goto error;
1502 }
1503
Radek Krejcieb00f512015-07-01 16:44:58 +02001504 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001505 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001506 max = &((struct lys_node_leaflist *)target)->max;
1507 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001508 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001509 max = &((struct lys_node_list *)target)->max;
1510 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001511 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001512 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1513 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001514 goto error;
1515 }
1516
1517 GETVAL(value, node, "value");
1518 while (isspace(value[0])) {
1519 value++;
1520 }
1521
Radek Krejci0d7b2472016-02-12 11:11:03 +01001522 if (type && !strcmp(value, "unbounded")) {
1523 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001524 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001525 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001526 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001527 /* convert it to uint32_t */
1528 errno = 0;
1529 endptr = NULL;
1530 val = strtoul(value, &endptr, 10);
1531 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001532 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001533 goto error;
1534 }
1535 if (type) {
1536 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001537 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001538 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001539 } else {
1540 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001541 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001542 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001543 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 }
1545
1546 if (d->mod == LY_DEVIATE_ADD) {
1547 /* check that there is no current value */
1548 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001549 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1550 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001551 goto error;
1552 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001553 } else if (d->mod == LY_DEVIATE_RPL) {
1554 /* unfortunately, there is no way to check reliably that there
1555 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001556 }
1557
Michal Vaskof7e57d52016-03-07 11:31:09 +01001558 /* add (already checked) and replace */
1559 /* set new value specified in deviation */
1560 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001561
Pavol Vican09adcc32016-08-25 10:51:36 +02001562 /* check min-elements is smaller than max-elements */
1563 if (*max && *min > *max) {
1564 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001565 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001566 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1567 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001568 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001569 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1570 }
1571 goto error;
1572 }
1573
Radek Krejcieb00f512015-07-01 16:44:58 +02001574 return EXIT_SUCCESS;
1575
1576error:
1577
1578 return EXIT_FAILURE;
1579}
1580
Michal Vasko0d343d12015-08-24 14:57:36 +02001581/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001582static int
Michal Vasko88c29542015-11-27 14:57:53 +01001583fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1584 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001585{
1586 const char *value, **stritem;
1587 struct lyxml_elem *next, *child, *develem;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001588 int c_dev = 0, c_must, c_uniq, c_dflt;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001589 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001590 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001591 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001592 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001593 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001594 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001595 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001596 struct lys_node_leaf *leaf = NULL;
1597 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001598 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001599 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001600 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001601 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001602 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001603 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001604 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02001605
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001606 ctx = module->ctx;
1607
Radek Krejcieb00f512015-07-01 16:44:58 +02001608 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001609 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001610 if (!dev->target_name) {
1611 goto error;
1612 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001613
1614 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001615 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1616 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001617 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001618 goto error;
1619 }
Radek Krejcic4283442016-04-22 09:19:27 +02001620 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001621 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1622 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001623 goto error;
1624 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001625
1626 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001627 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1628 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001629 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001630 continue;
1631 }
1632
Radek Krejcieb00f512015-07-01 16:44:58 +02001633 if (!strcmp(child->name, "description")) {
1634 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001635 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001636 goto error;
1637 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001638 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001639 if (!dev->dsc) {
1640 goto error;
1641 }
1642 } else if (!strcmp(child->name, "reference")) {
1643 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001644 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 goto error;
1646 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001647 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001648 if (!dev->ref) {
1649 goto error;
1650 }
1651 } else if (!strcmp(child->name, "deviate")) {
1652 c_dev++;
1653
Michal Vasko345da0a2015-12-02 10:35:55 +01001654 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001655 * further processed later
1656 */
1657 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001658
Radek Krejcieb00f512015-07-01 16:44:58 +02001659 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001660 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001661 goto error;
1662 }
1663
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001664 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 }
1666
1667 if (c_dev) {
1668 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001669 if (!dev->deviate) {
1670 LOGMEM;
1671 goto error;
1672 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001673 } else {
1674 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1675 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001676 }
1677
1678 LY_TREE_FOR(yin->child, develem) {
1679 /* init */
1680 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001681 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 c_must = 0;
1683 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001684 c_dflt = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001685
1686 /* get deviation type */
1687 GETVAL(value, develem, "value");
1688 if (!strcmp(value, "not-supported")) {
1689 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1690 /* no property expected in this case */
1691 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001692 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001693 goto error;
1694 }
1695
Radek Krejci5b917642015-07-02 09:03:13 +02001696 /* and neither any other deviate statement is expected,
1697 * not-supported deviation must be the only deviation of the target
1698 */
1699 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001700 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1701 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001702 goto error;
1703 }
1704
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001705 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001706 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1707 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1708 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001709 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1710 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001711 goto error;
1712 }
1713 }
1714 }
Radek Krejci5b917642015-07-02 09:03:13 +02001715
Michal Vaskoff006c12016-02-17 11:15:19 +01001716 /* unlink and store the original node */
1717 lys_node_unlink(dev_target);
1718 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001719
Radek Krejci5b917642015-07-02 09:03:13 +02001720 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02001721 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02001722 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001723 } else if (!strcmp(value, "add")) {
1724 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1725 } else if (!strcmp(value, "replace")) {
1726 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1727 } else if (!strcmp(value, "delete")) {
1728 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1729 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001730 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001731 goto error;
1732 }
1733 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001734 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001735
Michal Vaskoff006c12016-02-17 11:15:19 +01001736 /* store a shallow copy of the original node */
1737 if (!dev->orig_node) {
1738 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001739 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01001740 /* just to be safe */
1741 if (tmp_unres.count) {
1742 LOGINT;
1743 goto error;
1744 }
1745 }
1746
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 /* process deviation properties */
1748 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001749 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1750 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001751 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001752 continue;
1753 }
1754
Radek Krejcieb00f512015-07-01 16:44:58 +02001755 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001756 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001757 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001758 goto error;
1759 }
1760
1761 /* for we deviate from RFC 6020 and allow config property even it is/is not
1762 * specified in the target explicitly since config property inherits. So we expect
1763 * that config is specified in every node. But for delete, we check that the value
1764 * is the same as here in deviation
1765 */
1766 GETVAL(value, child, "value");
1767 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001768 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001769 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001770 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001772 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001773 goto error;
1774 }
1775
1776 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001777 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001778 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001779 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001780 } else { /* add and replace are the same in this case */
1781 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001782 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001783
1784 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001785 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001786 }
1787 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001788 c_dflt++;
1789
1790 /* check target node type */
1791 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1792 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1793 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1794 goto error;
1795 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1796 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1797 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1798 goto error;
1799 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
1800 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1801 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001802 goto error;
1803 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001804
Radek Krejcid5a5c282016-08-15 15:38:08 +02001805 /* skip lyxml_free() at the end of the loop, this node will be processed later */
1806 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02001807
Radek Krejcieb00f512015-07-01 16:44:58 +02001808 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001809 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001810 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 goto error;
1812 }
1813
1814 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001815 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001816 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1817 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001818 goto error;
1819 }
1820
1821 GETVAL(value, child, "value");
1822 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001823 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001825 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001826 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001827 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001828 goto error;
1829 }
1830
1831 if (d->mod == LY_DEVIATE_ADD) {
1832 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001833 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001834 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1835 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001836 goto error;
1837 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001838
Radek Krejci841ec082016-04-05 13:05:17 +02001839 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02001840 if (d->flags & LYS_MAND_TRUE) {
1841 if (dev_target->nodetype == LYS_CHOICE) {
1842 if (((struct lys_node_choice *)(dev_target))->dflt) {
1843 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1844 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1845 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
1846 goto error;
1847 }
1848 } else if (dev_target->nodetype == LYS_LEAF) {
1849 if (((struct lys_node_leaf *)(dev_target))->dflt) {
1850 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1851 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1852 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
1853 goto error;
1854 }
1855 }
Radek Krejci841ec082016-04-05 13:05:17 +02001856 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001857
Michal Vasko21be1b32016-03-07 12:31:34 +01001858 dev_target->flags |= d->flags & LYS_MAND_MASK;
1859 } else if (d->mod == LY_DEVIATE_RPL) {
1860 /* check that there was a value before */
1861 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001862 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1863 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001864 goto error;
1865 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001866
Michal Vasko21be1b32016-03-07 12:31:34 +01001867 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001868 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001869 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001870 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001871 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001872 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001873 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001874
1875 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
1876 for (parent = dev_target->parent;
1877 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1878 parent = parent->parent) {
1879 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1880 /* stop also on presence containers */
1881 break;
1882 }
1883 }
1884 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1885 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1886 if (lyp_check_mandatory_choice(parent)) {
1887 goto error;
1888 }
1889 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001890 } else if (!strcmp(child->name, "min-elements")) {
1891 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001892 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001893 goto error;
1894 }
1895 f_min = 1;
1896
Michal Vasko60f4b452016-02-12 11:02:55 +01001897 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001898 goto error;
1899 }
1900 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001901 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001902 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001903 goto error;
1904 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001905 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001906
Michal Vasko60f4b452016-02-12 11:02:55 +01001907 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001908 goto error;
1909 }
1910 } else if (!strcmp(child->name, "must")) {
1911 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001912 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001913 continue;
1914 } else if (!strcmp(child->name, "type")) {
1915 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001916 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001917 goto error;
1918 }
1919
Michal Vaskof7e57d52016-03-07 11:31:09 +01001920 /* add, del type is forbidden */
1921 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001922 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001923 goto error;
1924 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001925 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001926 goto error;
1927 }
1928
Radek Krejcieb00f512015-07-01 16:44:58 +02001929 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001930 if (dev_target->nodetype == LYS_LEAF) {
1931 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001932 if (((struct lys_node_leaf *)dev_target)->dflt) {
1933 ly_set_add(dflt_check, dev_target, 0);
1934 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001935 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1936 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001937 if (((struct lys_node_leaflist *)dev_target)->dflt) {
1938 ly_set_add(dflt_check, dev_target, 0);
1939 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001940 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001941 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1942 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001943 goto error;
1944 }
1945
Radek Krejcieb00f512015-07-01 16:44:58 +02001946 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001947 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001948 /* HACK for unres */
1949 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001950 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001951 goto error;
1952 }
1953 d->type = t;
1954 } else if (!strcmp(child->name, "unique")) {
1955 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001956 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 continue;
1958 } else if (!strcmp(child->name, "units")) {
1959 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001960 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001961 goto error;
1962 }
1963
1964 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001965 if (dev_target->nodetype == LYS_LEAFLIST) {
1966 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1967 } else if (dev_target->nodetype == LYS_LEAF) {
1968 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001969 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001970 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1971 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001972 goto error;
1973 }
1974
1975 /* get units value */
1976 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001977 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001978
1979 /* apply to target */
1980 if (d->mod == LY_DEVIATE_ADD) {
1981 /* check that there is no current value */
1982 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001983 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1984 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001985 goto error;
1986 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001987
Michal Vasko21be1b32016-03-07 12:31:34 +01001988 *stritem = lydict_insert(ctx, value, 0);
1989 } else if (d->mod == LY_DEVIATE_RPL) {
1990 /* check that there was a value before */
1991 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001992 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1993 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001994 goto error;
1995 }
1996
1997 lydict_remove(ctx, *stritem);
1998 *stritem = lydict_insert(ctx, value, 0);
1999 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002000 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002001 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002002 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2003 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002004 goto error;
2005 }
2006 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002007 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002008 }
2009 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002010 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002011 goto error;
2012 }
2013
Michal Vasko88c29542015-11-27 14:57:53 +01002014 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002015 }
2016
2017 if (c_must) {
2018 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002019 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002020 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002021 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2022 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002023 break;
Radek Krejci76512572015-08-04 09:47:08 +02002024 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002025 trg_must = &((struct lys_node_container *)dev_target)->must;
2026 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002027 break;
Radek Krejci76512572015-08-04 09:47:08 +02002028 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002029 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2030 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002031 break;
Radek Krejci76512572015-08-04 09:47:08 +02002032 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002033 trg_must = &((struct lys_node_list *)dev_target)->must;
2034 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002035 break;
Radek Krejci76512572015-08-04 09:47:08 +02002036 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002037 case LYS_ANYDATA:
2038 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2039 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002040 break;
2041 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002042 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2043 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002044 goto error;
2045 }
2046
Michal Vaskoe9914d12016-10-07 14:32:37 +02002047 dev_target->flags &= ~LYS_VALID_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002048
Radek Krejcieb00f512015-07-01 16:44:58 +02002049 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002050 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002051 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002052 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002053 } else if (d->mod == LY_DEVIATE_ADD) {
2054 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002055 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002056 if (!d->must) {
2057 LOGMEM;
2058 goto error;
2059 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002060 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002061 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002062 d->must_size = c_must;
2063 } else { /* LY_DEVIATE_DEL */
2064 d->must = calloc(c_must, sizeof *d->must);
2065 }
Michal Vasko253035f2015-12-17 16:58:13 +01002066 if (!d->must) {
2067 LOGMEM;
2068 goto error;
2069 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002070 }
2071 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002072 /* replace unique is forbidden */
2073 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002074 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002075 goto error;
2076 }
2077
Radek Krejcieb00f512015-07-01 16:44:58 +02002078 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002079 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002080 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2081 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002082 goto error;
2083 }
2084
Michal Vasko60f4b452016-02-12 11:02:55 +01002085 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002086 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002087 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002088 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002089 list->unique = d->unique;
2090 d->unique = &list->unique[list->unique_size];
2091 d->unique_size = c_uniq;
2092 } else { /* LY_DEVIATE_DEL */
2093 d->unique = calloc(c_uniq, sizeof *d->unique);
2094 }
Michal Vasko253035f2015-12-17 16:58:13 +01002095 if (!d->unique) {
2096 LOGMEM;
2097 goto error;
2098 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002099 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002100 if (c_dflt) {
2101 if (d->mod == LY_DEVIATE_ADD) {
2102 /* check that there is no current value */
2103 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2104 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2105 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2106 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2107 goto error;
2108 }
2109
2110 /* check collision with mandatory/min-elements */
2111 if ((dev_target->flags & LYS_MAND_TRUE) ||
2112 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2113 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2114 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2115 "Adding the \"default\" statement is forbidden on %s statement.",
2116 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2117 goto error;
2118 }
2119 } else if (d->mod == LY_DEVIATE_RPL) {
2120 /* check that there was a value before */
2121 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2122 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2123 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2124 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2125 goto error;
2126 }
2127 }
2128
2129 if (dev_target->nodetype == LYS_LEAFLIST) {
2130 /* reallocate default list in the target */
2131 llist = (struct lys_node_leaflist *)dev_target;
2132 if (d->mod == LY_DEVIATE_ADD) {
2133 /* reallocate (enlarge) the unique array of the target */
2134 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2135 } else if (d->mod == LY_DEVIATE_RPL) {
2136 /* reallocate (replace) the unique array of the target */
2137 for (i = 0; i < llist->dflt_size; i++) {
2138 lydict_remove(llist->module->ctx, llist->dflt[i]);
2139 }
2140 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2141 llist->dflt_size = 0;
2142 }
2143 }
2144 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2145 if (!d->dflt) {
2146 LOGMEM;
2147 goto error;
2148 }
2149 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002150
2151 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002152 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002153 if (!strcmp(child->name, "must")) {
2154 if (d->mod == LY_DEVIATE_DEL) {
2155 if (fill_yin_must(module, child, &d->must[d->must_size])) {
2156 goto error;
2157 }
2158
2159 /* find must to delete, we are ok with just matching conditions */
2160 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002161 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002162 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002163 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002164 /* ... and maintain the array */
2165 (*trg_must_size)--;
2166 if (i != *trg_must_size) {
2167 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2168 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2169 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2170 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2171 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2172 }
2173 if (!(*trg_must_size)) {
2174 free(*trg_must);
2175 *trg_must = NULL;
2176 } else {
2177 (*trg_must)[*trg_must_size].expr = NULL;
2178 (*trg_must)[*trg_must_size].dsc = NULL;
2179 (*trg_must)[*trg_must_size].ref = NULL;
2180 (*trg_must)[*trg_must_size].eapptag = NULL;
2181 (*trg_must)[*trg_must_size].emsg = NULL;
2182 }
2183
2184 i = -1; /* set match flag */
2185 break;
2186 }
2187 }
2188 d->must_size++;
2189 if (i != -1) {
2190 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002191 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002192 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002193 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002194 goto error;
2195 }
2196 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002197 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2198 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002199 goto error;
2200 }
2201 (*trg_must_size)++;
2202 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002203
2204 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002205 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002206 goto error;
2207 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002208 } else if (!strcmp(child->name, "unique")) {
2209 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002210 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002211 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002212 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002213 goto error;
2214 }
2215
2216 /* find unique structures to delete */
2217 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002218 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002219 continue;
2220 }
2221
Radek Krejci581ce772015-11-10 17:22:40 +01002222 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002223 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002224 break;
2225 }
2226 }
2227
Radek Krejci581ce772015-11-10 17:22:40 +01002228 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002229 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002230 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002231 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002232 }
2233 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002234 /* ... and maintain the array */
2235 list->unique_size--;
2236 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002237 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2238 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002239 }
2240
2241 if (!list->unique_size) {
2242 free(list->unique);
2243 list->unique = NULL;
2244 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002245 list->unique[list->unique_size].expr_size = 0;
2246 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002247 }
2248
2249 i = -1; /* set match flag */
2250 break;
2251 }
2252 }
2253
2254 d->unique_size++;
2255 if (i != -1) {
2256 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002257 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2258 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002259 goto error;
2260 }
2261 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002262 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002263 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002264 list->unique_size++;
2265 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002266 goto error;
2267 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002268 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002269 } else if (!strcmp(child->name, "default")) {
2270 GETVAL(value, child, "value");
2271 u = strlen(value);
2272 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2273
2274 if (dev_target->nodetype == LYS_CHOICE) {
2275 choice = (struct lys_node_choice *)dev_target;
2276 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2277 if (rc || !node) {
2278 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2279 goto error;
2280 }
2281 if (d->mod == LY_DEVIATE_DEL) {
2282 if (!choice->dflt || (choice->dflt != node)) {
2283 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2284 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2285 goto error;
2286 }
2287 } else { /* add or replace */
2288 choice->dflt = node;
2289 if (!choice->dflt) {
2290 /* default branch not found */
2291 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2292 goto error;
2293 }
2294 }
2295 } else if (dev_target->nodetype == LYS_LEAF) {
2296 leaf = (struct lys_node_leaf *)dev_target;
2297 if (d->mod == LY_DEVIATE_DEL) {
2298 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2299 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2300 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2301 goto error;
2302 }
2303 /* remove value */
2304 lydict_remove(ctx, leaf->dflt);
2305 leaf->dflt = NULL;
2306 } else { /* add (already checked) and replace */
2307 /* remove value */
2308 lydict_remove(ctx, leaf->dflt);
2309
2310 /* set new value */
2311 leaf->dflt = lydict_insert(ctx, value, u);
2312
2313 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2314 ly_set_add(dflt_check, dev_target, 0);
2315 }
2316 } else { /* LYS_LEAFLIST */
2317 llist = (struct lys_node_leaflist *)dev_target;
2318 if (d->mod == LY_DEVIATE_DEL) {
2319 /* find and remove the value in target list */
2320 for (i = 0; i < llist->dflt_size; i++) {
2321 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2322 /* match, remove the value */
2323 lydict_remove(llist->module->ctx, llist->dflt[i]);
2324 llist->dflt[i] = NULL;
2325 break;
2326 }
2327 }
2328 if (i == llist->dflt_size) {
2329 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2330 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2331 goto error;
2332 }
2333 } else {
2334 /* add or replace, anyway we place items into the deviate's list
2335 which propagates to the target */
2336 /* we just want to check that the value isn't already in the list */
2337 for (i = 0; i < llist->dflt_size; i++) {
2338 if (ly_strequal(llist->dflt[i], value, 1)) {
2339 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2340 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2341 goto error;
2342 }
2343 }
2344 /* store it in target node */
2345 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2346
2347 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2348 ly_set_add(dflt_check, dev_target, 0);
2349 }
2350 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002351 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002352 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002353
2354 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2355 /* consolidate the final list in the target after removing items from it */
2356 llist = (struct lys_node_leaflist *)dev_target;
2357 for (i = j = 0; j < llist->dflt_size; j++) {
2358 llist->dflt[i] = llist->dflt[j];
2359 if (llist->dflt[i]) {
2360 i++;
2361 }
2362 }
2363 llist->dflt_size = i + 1;
2364 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002365 }
2366
Michal Vasko43a1feb2016-03-07 12:03:02 +01002367 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002368 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002369 value = NULL;
2370 rc = EXIT_SUCCESS;
2371 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2372 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002373 value = leaf->dflt;
2374 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002375 } else { /* LYS_LEAFLIST */
2376 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2377 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002378 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2379 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002380 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002381 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002382 break;
2383 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002384 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002385
2386 }
2387 if (rc == -1) {
2388 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2389 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2390 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2391 dev->target_name);
2392 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002393 }
2394 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002395
Radek Krejci27fe55e2016-09-13 17:13:35 +02002396 /* mark all the affected modules as deviated and implemented */
2397 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2398 mod = lys_node_module(parent);
2399 if (module != mod) {
2400 mod->deviated = 1;
2401 lys_set_implemented(mod);
2402 }
2403 }
2404
Radek Krejcid5a5c282016-08-15 15:38:08 +02002405 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002406 return EXIT_SUCCESS;
2407
2408error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002409 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002410 return EXIT_FAILURE;
2411}
2412
Michal Vasko0d343d12015-08-24 14:57:36 +02002413/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002414static int
Radek Krejcib8048692015-08-05 13:36:34 +02002415fill_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 +02002416 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002417{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002419 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002420 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002421 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002422
Michal Vasko591e0b22015-08-13 13:53:43 +02002423 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002425 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002426 if (!aug->target_name) {
2427 goto error;
2428 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002430
Michal Vasko1d87a922015-08-21 12:57:16 +02002431 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002432 goto error;
2433 }
2434
2435 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002436 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2437 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002438 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002439 continue;
2440 }
2441
Radek Krejci3cf9e222015-06-18 11:37:50 +02002442 if (!strcmp(child->name, "if-feature")) {
2443 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002444 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002445 } else if (!strcmp(child->name, "when")) {
2446 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002448 goto error;
2449 }
2450
2451 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002452 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002453 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002454 goto error;
2455 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002456 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002457 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002458
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002459 /* check allowed data sub-statements */
2460 } else if (!strcmp(child->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002461 node = read_yin_container(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002462 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002463 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002464 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002465 node = read_yin_leaf(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002466 } else if (!strcmp(child->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002467 node = read_yin_list(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002468 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002469 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002470 } else if (!strcmp(child->name, "choice")) {
Pavol Vican9c3318f2016-10-24 11:32:48 +02002471 node = read_yin_choice(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002472 } else if (!strcmp(child->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002473 node = read_yin_case(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002474 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002475 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYXML, 1, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02002476 } else if (!strcmp(child->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002477 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYDATA, 1, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002478 } else if (!strcmp(child->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002479 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02002480 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002481 node = read_yin_notif(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002482 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002483 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002484 goto error;
2485 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002486
Radek Krejci1d82ef62015-08-07 14:44:40 +02002487 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002488 goto error;
2489 }
2490
Radek Krejci1d82ef62015-08-07 14:44:40 +02002491 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002492 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002493 }
2494
2495 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002496 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2497 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002498 LOGMEM;
2499 goto error;
2500 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002501 }
2502
2503 LY_TREE_FOR_SAFE(yin->child, next, child) {
2504 if (!strcmp(child->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02002505 ret = fill_yin_iffeature((struct lys_node *)aug, 0, child, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002506 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002507 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002508 goto error;
2509 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002510 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002511 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002512 }
2513
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002514 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002515 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002516 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002517 * when the uses does and cannot be resolved now for sure
2518 * (the grouping was not yet copied into uses).
2519 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002520 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002521 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002522 goto error;
2523 }
Michal Vasko49291b32015-08-06 09:49:41 +02002524 }
Radek Krejci106efc02015-06-10 14:36:27 +02002525
Michal Vasko508a50d2016-09-07 14:50:33 +02002526 /* check XPath dependencies */
2527 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2528 goto error;
2529 }
2530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002532
2533error:
2534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002536}
2537
Michal Vasko0d343d12015-08-24 14:57:36 +02002538/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002540fill_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 +02002541{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002542 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002543 struct lyxml_elem *sub, *next;
2544 const char *value;
2545 char *endptr;
2546 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci200bf712016-08-16 17:11:04 +02002547 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548 int r;
2549 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002550
Radek Krejci363bd4a2016-07-29 14:30:20 +02002551 assert(uses);
2552 module = uses->module; /* shorthand */
2553
Michal Vaskoe022a562016-09-27 14:24:15 +02002554 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CFG_PARSE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 goto error;
2556 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002557
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002558 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002559 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002560 if (!rfn->target_name) {
2561 goto error;
2562 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002565 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2566 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002567 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002568 continue;
2569 }
2570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 /* limited applicability */
2572 if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002573 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 /* check possibility of statements combination */
2576 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002577 if (c_dflt) {
2578 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002579 if (module->version < 2) {
2580 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2581 goto error;
2582 }
Radek Krejci200bf712016-08-16 17:11:04 +02002583 rfn->target_type &= LYS_LEAFLIST;
2584 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002585 if (module->version < 2) {
2586 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2587 } else {
2588 /* YANG 1.1 */
2589 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2590 }
Radek Krejci200bf712016-08-16 17:11:04 +02002591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002592 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002593 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2594 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 goto error;
2596 }
2597 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002598 if (module->version < 2) {
2599 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2600 } else {
2601 /* YANG 1.1 */
2602 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2603 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002605
Radek Krejci200bf712016-08-16 17:11:04 +02002606 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002607 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002608 } else if (!strcmp(sub->name, "mandatory")) {
2609 /* leaf, choice or anyxml */
2610 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002611 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002612 goto error;
2613 }
2614 /* just checking the flags in leaf is not sufficient, we would allow
2615 * multiple mandatory statements with the "false" value
2616 */
2617 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002619 /* check possibility of statements combination */
2620 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002621 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002622 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002623 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2624 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 goto error;
2626 }
2627 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002628 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002629 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 GETVAL(value, sub, "value");
2632 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002633 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002635 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002637 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 goto error;
2639 }
2640 } else if (!strcmp(sub->name, "min-elements")) {
2641 /* list or leaf-list */
2642 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002643 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002644 goto error;
2645 }
2646 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 /* check possibility of statements combination */
2649 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002650 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002652 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2653 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002654 goto error;
2655 }
2656 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002657 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660 GETVAL(value, sub, "value");
2661 while (isspace(value[0])) {
2662 value++;
2663 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 /* convert it to uint32_t */
2666 errno = 0;
2667 endptr = NULL;
2668 val = strtoul(value, &endptr, 10);
2669 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002670 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002671 goto error;
2672 }
2673 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002674 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002675 } else if (!strcmp(sub->name, "max-elements")) {
2676 /* list or leaf-list */
2677 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002678 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 goto error;
2680 }
2681 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002683 /* check possibility of statements combination */
2684 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002685 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002686 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002687 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2688 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002689 goto error;
2690 }
2691 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002692 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 GETVAL(value, sub, "value");
2696 while (isspace(value[0])) {
2697 value++;
2698 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002699
Radek Krejci0d7b2472016-02-12 11:11:03 +01002700 if (!strcmp(value, "unbounded")) {
2701 rfn->mod.list.max = 0;
2702 } else {
2703 /* convert it to uint32_t */
2704 errno = 0;
2705 endptr = NULL;
2706 val = strtoul(value, &endptr, 10);
2707 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002708 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002709 goto error;
2710 }
2711 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002713 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 } else if (!strcmp(sub->name, "presence")) {
2715 /* container */
2716 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002717 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002718 goto error;
2719 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 /* check possibility of statements combination */
2722 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002723 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002725 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2726 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 goto error;
2728 }
2729 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002730 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 GETVAL(value, sub, "value");
2734 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2735 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002736 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002737 /* check possibility of statements combination */
2738 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002739 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002741 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2742 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 goto error;
2744 }
2745 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002746 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002747 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002750 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002751
Radek Krejci363bd4a2016-07-29 14:30:20 +02002752 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2753 /* leaf, leaf-list, list, container or anyxml */
2754 /* check possibility of statements combination */
2755 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002756 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002757 if (!rfn->target_type) {
2758 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2759 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2760 goto error;
2761 }
2762 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002763 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002764 }
2765
2766 c_ftrs++;
2767 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002768 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002769 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002770 goto error;
2771 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002772
Michal Vasko345da0a2015-12-02 10:35:55 +01002773 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002776 /* process nodes with cardinality of 0..n */
2777 if (c_must) {
2778 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002779 if (!rfn->must) {
2780 LOGMEM;
2781 goto error;
2782 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002784 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002785 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002786 if (!rfn->iffeature) {
2787 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002788 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002789 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002790 }
Radek Krejci200bf712016-08-16 17:11:04 +02002791 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002792 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002793 if (!rfn->dflt) {
2794 LOGMEM;
2795 goto error;
2796 }
2797 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002798
Radek Krejci363bd4a2016-07-29 14:30:20 +02002799 LY_TREE_FOR(yin->child, sub) {
2800 if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02002801 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002802 rfn->iffeature_size++;
2803 if (r) {
2804 goto error;
2805 }
Radek Krejci200bf712016-08-16 17:11:04 +02002806 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002807 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2808 rfn->must_size++;
2809 if (r) {
2810 goto error;
2811 }
Radek Krejci200bf712016-08-16 17:11:04 +02002812 } else { /* default */
2813 GETVAL(value, sub, "value");
2814
2815 /* check for duplicity */
2816 for (r = 0; r < rfn->dflt_size; r++) {
2817 if (ly_strequal(rfn->dflt[r], value, 1)) {
2818 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2819 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2820 goto error;
2821 }
2822 }
2823 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02002824 }
2825 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002827 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002828
2829error:
2830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002832}
2833
Michal Vasko0d343d12015-08-24 14:57:36 +02002834/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002835static int
Radek Krejcib8048692015-08-05 13:36:34 +02002836fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002837{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 struct lyxml_elem *child;
2839 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002842 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2843 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002844 continue;
2845 }
2846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002847 if (!strcmp(child->name, "prefix")) {
2848 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002849 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 goto error;
2851 }
2852 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2853 } else if (!strcmp(child->name, "revision-date")) {
2854 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002855 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2856 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 }
2858 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002859 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860 goto error;
2861 }
2862 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002863 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002864 if (imp->dsc) {
2865 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2866 goto error;
2867 }
2868 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2869 if (!imp->dsc) {
2870 goto error;
2871 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002872 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002873 if (imp->ref) {
2874 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2875 goto error;
2876 }
2877 imp->ref = read_yin_subnode(module->ctx, child, "text");
2878 if (!imp->ref) {
2879 goto error;
2880 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002882 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 goto error;
2884 }
2885 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002887 /* check mandatory information */
2888 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002889 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 goto error;
2891 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002894
Pavol Vicane994fda2016-03-22 10:47:58 +01002895 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002896
2897error:
2898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002900}
2901
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002902/* logs directly
2903 * returns:
2904 * 0 - inc successfully filled
2905 * -1 - error, inc is cleaned
2906 * 1 - duplication, ignore the inc structure, inc is cleaned
2907 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002909fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2910 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002911{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002912 struct lyxml_elem *child;
2913 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002916 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2917 /* garbage */
2918 continue;
2919 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 if (!strcmp(child->name, "revision-date")) {
2921 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002922 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 goto error;
2924 }
2925 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002926 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 goto error;
2928 }
2929 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002930 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002931 if (inc->dsc) {
2932 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2933 goto error;
2934 }
2935 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2936 if (!inc->dsc) {
2937 goto error;
2938 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002939 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002940 if (inc->ref) {
2941 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2942 goto error;
2943 }
2944 inc->ref = read_yin_subnode(module->ctx, child, "text");
2945 if (!inc->ref) {
2946 goto error;
2947 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002948 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002949 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 goto error;
2951 }
2952 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002954 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002955
Pavol Vican0adf01d2016-03-22 12:29:33 +01002956 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002957
2958error:
2959
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002960 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002961}
2962
Michal Vasko0d343d12015-08-24 14:57:36 +02002963/* logs directly
2964 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002965 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002966 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002967 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002968 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969static int
Radek Krejcib8048692015-08-05 13:36:34 +02002970read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002971 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002972{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 const char *value;
2974 struct lyxml_elem *sub, *next;
2975 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002978 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002980
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 if (opt & OPT_IDENT) {
2982 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002983 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002984 goto error;
2985 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002986 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002988
Radek Krejci6764bb32015-07-03 15:16:04 +02002989 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002990 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002991 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002992 }
2993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 /* process local parameters */
2995 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002996 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002997 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002998 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002999 continue;
3000 }
3001 if (strcmp(sub->ns->value, LY_NSYIN)) {
3002 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02003003 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003004 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003005 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02003006 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003007 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02003008 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003009 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02003010 goto error;
3011 }
3012 }
3013
3014 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003015 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003016 continue;
3017 }
3018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003020 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003021 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 goto error;
3023 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003024 node->dsc = read_yin_subnode(ctx, sub, "text");
3025 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003026 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 }
3028 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003029 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003030 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 goto error;
3032 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003033 node->ref = read_yin_subnode(ctx, sub, "text");
3034 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003035 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003036 }
3037 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003038 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003039 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003040 goto error;
3041 }
3042 GETVAL(value, sub, "value");
3043 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003044 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003046 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003048 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003050 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003051 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003053 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3054 if (opt & OPT_CFG_PARSE) {
3055 if (node->flags & LYS_CONFIG_MASK) {
3056 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3057 goto error;
3058 }
3059 GETVAL(value, sub, "value");
3060 if (!strcmp(value, "false")) {
3061 node->flags |= LYS_CONFIG_R;
3062 } else if (!strcmp(value, "true")) {
3063 node->flags |= LYS_CONFIG_W;
3064 } else {
3065 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3066 goto error;
3067 }
3068 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003071 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 continue;
3073 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003074 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003076
Michal Vaskoe022a562016-09-27 14:24:15 +02003077 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003079 if (parent) {
3080 node->flags |= parent->flags & LYS_CONFIG_MASK;
3081 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003082 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003083 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 }
3085 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003088
3089error:
3090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003092}
3093
Michal Vasko0d343d12015-08-24 14:57:36 +02003094/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003095static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003096read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003097{
Radek Krejci76512572015-08-04 09:47:08 +02003098 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003099 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003100 const char *value;
3101
3102 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003103 if (!retval) {
3104 LOGMEM;
3105 return NULL;
3106 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003107
3108 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003109 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003110 if (!retval->cond) {
3111 goto error;
3112 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003113
Radek Krejci73adb602015-07-02 18:07:40 +02003114 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003115 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3116 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003117 continue;
3118 }
3119
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003120 if (!strcmp(child->name, "description")) {
3121 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003122 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003123 goto error;
3124 }
3125 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3126 if (!retval->dsc) {
3127 goto error;
3128 }
3129 } else if (!strcmp(child->name, "reference")) {
3130 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003131 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003132 goto error;
3133 }
3134 retval->ref = read_yin_subnode(module->ctx, child, "text");
3135 if (!retval->ref) {
3136 goto error;
3137 }
3138 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003139 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003140 goto error;
3141 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003142 }
3143
3144 return retval;
3145
3146error:
3147
Michal Vasko0308dd62015-10-07 09:14:40 +02003148 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003149 return NULL;
3150}
3151
Michal Vasko0d343d12015-08-24 14:57:36 +02003152/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003153static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003154read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003155 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003156{
Michal Vasko29fc0182015-08-24 15:02:39 +02003157 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003158 struct lys_node_case *cs;
3159 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02003160 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003161
Radek Krejcie867c852015-08-27 09:52:34 +02003162 /* init */
3163 memset(&root, 0, sizeof root);
3164
Radek Krejci1d82ef62015-08-07 14:44:40 +02003165 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003166 if (!cs) {
3167 LOGMEM;
3168 return NULL;
3169 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003170 cs->nodetype = LYS_CASE;
3171 cs->prev = (struct lys_node *)cs;
3172 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003173
Michal Vaskoe022a562016-09-27 14:24:15 +02003174 if (read_yin_common(module, parent, retval, yin,
3175 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0) | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 goto error;
3177 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003178
Radek Krejcia9544502015-08-14 08:24:29 +02003179 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3180
Michal Vasko3a0043f2015-08-12 12:11:30 +02003181 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003182 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003183 goto error;
3184 }
3185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 /* process choice's specific children */
3187 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003188 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3189 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003190 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003191 continue;
3192 }
3193
Michal Vasko29fc0182015-08-24 15:02:39 +02003194 if (!strcmp(sub->name, "container") ||
3195 !strcmp(sub->name, "leaf-list") ||
3196 !strcmp(sub->name, "leaf") ||
3197 !strcmp(sub->name, "list") ||
3198 !strcmp(sub->name, "uses") ||
3199 !strcmp(sub->name, "choice") ||
3200 !strcmp(sub->name, "anyxml")) {
3201
Michal Vaskof3930de2015-10-22 12:03:59 +02003202 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003203 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003204 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003205 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01003206 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02003207 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003208 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003209 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003210 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003211 goto error;
3212 }
3213
Radek Krejci1d82ef62015-08-07 14:44:40 +02003214 cs->when = read_yin_when(module, sub);
3215 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003216 goto error;
3217 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003218
Michal Vasko345da0a2015-12-02 10:35:55 +01003219 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003220 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003221 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003225
Radek Krejci3cf9e222015-06-18 11:37:50 +02003226 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003227 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3228 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003229 LOGMEM;
3230 goto error;
3231 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003232 }
Radek Krejci73adb602015-07-02 18:07:40 +02003233 LY_TREE_FOR(yin->child, sub) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003234 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003235 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003236 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003237 goto error;
3238 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 }
Radek Krejcib388c152015-06-04 17:03:03 +02003240
Michal Vasko29fc0182015-08-24 15:02:39 +02003241 /* last part - process data nodes */
3242 LY_TREE_FOR_SAFE(root.child, next, sub) {
3243 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003244 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003245 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003246 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003247 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003248 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003249 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003250 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003251 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003252 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003253 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003254 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003255 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003256 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003257 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003258 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003259 }
3260 if (!node) {
3261 goto error;
3262 }
3263
Michal Vasko345da0a2015-12-02 10:35:55 +01003264 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003265 }
3266
Michal Vasko508a50d2016-09-07 14:50:33 +02003267 /* check XPath dependencies */
3268 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3269 goto error;
3270 }
3271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003273
3274error:
3275
Michal Vasko29fc0182015-08-24 15:02:39 +02003276 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003277 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003278 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003279 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003282}
3283
Michal Vasko0d343d12015-08-24 14:57:36 +02003284/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003285static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003286read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3287 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003288{
Radek Krejci629cdef2016-06-06 15:06:36 +02003289 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003291 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003292 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003293 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02003294 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003297 if (!choice) {
3298 LOGMEM;
3299 return NULL;
3300 }
Radek Krejci76512572015-08-04 09:47:08 +02003301 choice->nodetype = LYS_CHOICE;
3302 choice->prev = (struct lys_node *)choice;
3303 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003304
Michal Vaskoe022a562016-09-27 14:24:15 +02003305 if (read_yin_common(module, parent, retval, yin,
3306 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3307 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 goto error;
3309 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003310
Radek Krejcia9544502015-08-14 08:24:29 +02003311 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3312
Michal Vasko3a0043f2015-08-12 12:11:30 +02003313 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003314 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003315 goto error;
3316 }
3317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 /* process choice's specific children */
3319 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003320 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3321 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003322 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003323 continue;
3324 }
3325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003327 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 goto error;
3329 }
3330 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003331 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 goto error;
3333 }
3334 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003335 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 goto error;
3337 }
3338 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003339 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 goto error;
3341 }
3342 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003343 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 goto error;
3345 }
3346 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003347 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003348 goto error;
3349 }
3350 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003351 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
3354 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003355 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003356 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 goto error;
3358 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003359 dflt = sub;
3360 lyxml_unlink_elem(ctx, dflt, 0);
3361
Radek Krejcif9a312c2016-06-06 15:14:30 +02003362 continue;
3363 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 } else if (!strcmp(sub->name, "mandatory")) {
3366 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003367 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 goto error;
3369 }
3370 /* just checking the flags in leaf is not sufficient, we would allow
3371 * multiple mandatory statements with the "false" value
3372 */
3373 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 GETVAL(value, sub, "value");
3376 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003377 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003378 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003379 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003380 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003381 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 goto error;
3383 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003384 } else if (!strcmp(sub->name, "when")) {
3385 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003386 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003387 goto error;
3388 }
3389
3390 choice->when = read_yin_when(module, sub);
3391 if (!choice->when) {
3392 goto error;
3393 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003394 } else if (!strcmp(sub->name, "if-feature")) {
3395 c_ftrs++;
3396
Michal Vasko345da0a2015-12-02 10:35:55 +01003397 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003398 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003399 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003400 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02003401 goto error;
3402 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003404 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003407
Radek Krejci1d82ef62015-08-07 14:44:40 +02003408 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003409 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003411
Radek Krejci3cf9e222015-06-18 11:37:50 +02003412 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003413 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3414 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003415 LOGMEM;
3416 goto error;
3417 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003418 }
3419
Radek Krejci73adb602015-07-02 18:07:40 +02003420 LY_TREE_FOR(yin->child, sub) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003421 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003422 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003423 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003424 goto error;
3425 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003426 }
3427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003429 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003430 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
3431 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 goto error;
3433 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003436 if (dflt) {
3437 GETVAL(value, dflt, "value");
3438 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003439 goto error;
3440 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003441 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003443
Michal Vasko508a50d2016-09-07 14:50:33 +02003444 /* check XPath dependencies */
3445 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3446 goto error;
3447 }
3448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003450
3451error:
3452
Radek Krejci629cdef2016-06-06 15:06:36 +02003453 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003454 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003457}
3458
Michal Vasko0d343d12015-08-24 14:57:36 +02003459/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003460static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003461read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
3462 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003463{
Radek Krejci76512572015-08-04 09:47:08 +02003464 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003465 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 struct lyxml_elem *sub, *next;
3467 const char *value;
3468 int r;
3469 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003470 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003473 if (!anyxml) {
3474 LOGMEM;
3475 return NULL;
3476 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003477 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003478 anyxml->prev = (struct lys_node *)anyxml;
3479 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003480
Michal Vaskoe022a562016-09-27 14:24:15 +02003481 if (read_yin_common(module, parent, retval, yin,
3482 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3483 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 goto error;
3485 }
Radek Krejci863c2852015-06-03 15:47:11 +02003486
Radek Krejcia9544502015-08-14 08:24:29 +02003487 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003488
Radek Krejcic189a952016-07-11 15:27:07 +02003489 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003490 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003491 goto error;
3492 }
3493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003495 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3496 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003497 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003498 continue;
3499 }
3500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 if (!strcmp(sub->name, "mandatory")) {
3502 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003503 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 goto error;
3505 }
3506 /* just checking the flags in leaf is not sufficient, we would allow
3507 * multiple mandatory statements with the "false" value
3508 */
3509 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 GETVAL(value, sub, "value");
3512 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003513 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003514 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003515 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003516 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003517 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 goto error;
3519 }
3520 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003521 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003522 } else if (!strcmp(sub->name, "when")) {
3523 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003524 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003525 goto error;
3526 }
3527
3528 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003529 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003530 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003531 goto error;
3532 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003533 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 } else if (!strcmp(sub->name, "must")) {
3535 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003536 } else if (!strcmp(sub->name, "if-feature")) {
3537 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003540 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 }
3543 }
Radek Krejci863c2852015-06-03 15:47:11 +02003544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 /* middle part - process nodes with cardinality of 0..n */
3546 if (c_must) {
3547 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003548 if (!anyxml->must) {
3549 LOGMEM;
3550 goto error;
3551 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003553 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003554 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3555 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003556 LOGMEM;
3557 goto error;
3558 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003559 }
Radek Krejci863c2852015-06-03 15:47:11 +02003560
Radek Krejci73adb602015-07-02 18:07:40 +02003561 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003563 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3564 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 if (r) {
3566 goto error;
3567 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003568 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003569 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003570 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003571 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003572 goto error;
3573 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 }
Radek Krejci863c2852015-06-03 15:47:11 +02003576
Michal Vasko508a50d2016-09-07 14:50:33 +02003577 /* check XPath dependencies */
3578 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3579 goto error;
3580 }
3581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003583
3584error:
3585
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003586 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003589}
3590
Michal Vasko0d343d12015-08-24 14:57:36 +02003591/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003592static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003593read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003594 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003595{
Radek Krejci76512572015-08-04 09:47:08 +02003596 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003597 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003598 struct lyxml_elem *sub, *next;
3599 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003600 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003601 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003604 if (!leaf) {
3605 LOGMEM;
3606 return NULL;
3607 }
Radek Krejci76512572015-08-04 09:47:08 +02003608 leaf->nodetype = LYS_LEAF;
3609 leaf->prev = (struct lys_node *)leaf;
3610 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003611
Michal Vaskoe022a562016-09-27 14:24:15 +02003612 if (read_yin_common(module, parent, retval, yin,
3613 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3614 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 goto error;
3616 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003617
Radek Krejcia9544502015-08-14 08:24:29 +02003618 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003619
Radek Krejcic189a952016-07-11 15:27:07 +02003620 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003621 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003622 goto error;
3623 }
3624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003626 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3627 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003628 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003629 continue;
3630 }
3631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003633 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003634 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 goto error;
3636 }
Michal Vasko88c29542015-11-27 14:57:53 +01003637 /* HACK for unres */
3638 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003639 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003640 /* postpone type resolution when if-feature parsing is done since we need
3641 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003642 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 } else if (!strcmp(sub->name, "default")) {
3644 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003645 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003646 goto error;
3647 }
3648 GETVAL(value, sub, "value");
3649 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3650 } else if (!strcmp(sub->name, "units")) {
3651 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 goto error;
3654 }
3655 GETVAL(value, sub, "name");
3656 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3657 } else if (!strcmp(sub->name, "mandatory")) {
3658 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003659 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 goto error;
3661 }
3662 /* just checking the flags in leaf is not sufficient, we would allow
3663 * multiple mandatory statements with the "false" value
3664 */
3665 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 GETVAL(value, sub, "value");
3668 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003669 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003670 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003671 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003672 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003673 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003674 goto error;
3675 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003676 } else if (!strcmp(sub->name, "when")) {
3677 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003678 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003679 goto error;
3680 }
3681
3682 leaf->when = read_yin_when(module, sub);
3683 if (!leaf->when) {
3684 goto error;
3685 }
3686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003688 c_must++;
3689 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003690 } else if (!strcmp(sub->name, "if-feature")) {
3691 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003692 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003695 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003698
Michal Vasko88c29542015-11-27 14:57:53 +01003699 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003703 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003704 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 goto error;
3706 }
Michal Vasko478c4652016-07-21 12:55:01 +02003707 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3708 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3709 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3710 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3711 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 /* middle part - process nodes with cardinality of 0..n */
3715 if (c_must) {
3716 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003717 if (!leaf->must) {
3718 LOGMEM;
3719 goto error;
3720 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003722 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003723 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3724 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003725 LOGMEM;
3726 goto error;
3727 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003728 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003729
Radek Krejci73adb602015-07-02 18:07:40 +02003730 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003732 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3733 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 if (r) {
3735 goto error;
3736 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003737 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003738 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003739 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003740 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003741 goto error;
3742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003745
Radek Krejcicbb473e2016-09-16 14:48:32 +02003746 /* finalize type parsing */
3747 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
3748 leaf->type.der = NULL;
3749 goto error;
3750 }
3751
3752 /* check default value (if not defined, there still could be some restrictions
3753 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01003754 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt)) == -1) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02003755 goto error;
3756 }
3757
Michal Vasko508a50d2016-09-07 14:50:33 +02003758 /* check XPath dependencies */
3759 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3760 goto error;
3761 }
3762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003764
3765error:
3766
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003767 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003770}
3771
Michal Vasko0d343d12015-08-24 14:57:36 +02003772/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003773static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003774read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003775 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776{
Radek Krejci76512572015-08-04 09:47:08 +02003777 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003778 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003779 struct lyxml_elem *sub, *next;
3780 const char *value;
3781 char *endptr;
3782 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003783 int r, has_type = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003784 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003785 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003788 if (!llist) {
3789 LOGMEM;
3790 return NULL;
3791 }
Radek Krejci76512572015-08-04 09:47:08 +02003792 llist->nodetype = LYS_LEAFLIST;
3793 llist->prev = (struct lys_node *)llist;
3794 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003795
Michal Vaskoe022a562016-09-27 14:24:15 +02003796 if (read_yin_common(module, parent, retval, yin,
3797 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3798 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 goto error;
3800 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003801
Radek Krejcia9544502015-08-14 08:24:29 +02003802 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003803
Radek Krejcic189a952016-07-11 15:27:07 +02003804 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003805 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003806 goto error;
3807 }
3808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003810 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3811 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003812 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003813 continue;
3814 }
3815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003817 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003818 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 goto error;
3820 }
Michal Vasko88c29542015-11-27 14:57:53 +01003821 /* HACK for unres */
3822 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003823 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003824 /* postpone type resolution when if-feature parsing is done since we need
3825 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003826 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 } else if (!strcmp(sub->name, "units")) {
3828 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003829 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 goto error;
3831 }
3832 GETVAL(value, sub, "name");
3833 llist->units = lydict_insert(module->ctx, value, strlen(value));
3834 } else if (!strcmp(sub->name, "ordered-by")) {
3835 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003836 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 goto error;
3838 }
3839 /* just checking the flags in llist is not sufficient, we would
3840 * allow multiple ordered-by statements with the "system" value
3841 */
3842 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003843
Radek Krejci1574a8d2015-08-03 14:16:52 +02003844 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3846 * state data
3847 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003848 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 continue;
3850 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 GETVAL(value, sub, "value");
3853 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003854 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003856 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003858 } /* else system is the default value, so we can ignore it */
3859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003860 } else if (!strcmp(sub->name, "must")) {
3861 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003862 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003863 } else if (!strcmp(sub->name, "if-feature")) {
3864 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003866 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
3867 c_dflt++;
3868 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 } else if (!strcmp(sub->name, "min-elements")) {
3871 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003872 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 goto error;
3874 }
3875 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 GETVAL(value, sub, "value");
3878 while (isspace(value[0])) {
3879 value++;
3880 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 /* convert it to uint32_t */
3883 errno = 0;
3884 endptr = NULL;
3885 val = strtoul(value, &endptr, 10);
3886 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003887 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 goto error;
3889 }
3890 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003891 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003892 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3893 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003894 goto error;
3895 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 } else if (!strcmp(sub->name, "max-elements")) {
3897 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003898 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 goto error;
3900 }
3901 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003903 GETVAL(value, sub, "value");
3904 while (isspace(value[0])) {
3905 value++;
3906 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003907
Radek Krejci0d7b2472016-02-12 11:11:03 +01003908 if (!strcmp(value, "unbounded")) {
3909 llist->max = 0;
3910 } else {
3911 /* convert it to uint32_t */
3912 errno = 0;
3913 endptr = NULL;
3914 val = strtoul(value, &endptr, 10);
3915 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003916 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003917 goto error;
3918 }
3919 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003920 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003921 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3922 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003923 goto error;
3924 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003926 } else if (!strcmp(sub->name, "when")) {
3927 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003928 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003929 goto error;
3930 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003931
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003932 llist->when = read_yin_when(module, sub);
3933 if (!llist->when) {
3934 goto error;
3935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003937 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003939 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003940
Michal Vasko88c29542015-11-27 14:57:53 +01003941 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003945 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003946 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 goto error;
3948 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003950 /* middle part - process nodes with cardinality of 0..n */
3951 if (c_must) {
3952 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003953 if (!llist->must) {
3954 LOGMEM;
3955 goto error;
3956 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003958 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003959 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3960 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003961 LOGMEM;
3962 goto error;
3963 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003964 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003965 if (c_dflt) {
3966 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
3967 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003968 LOGMEM;
3969 goto error;
3970 }
3971 }
3972
Radek Krejci73adb602015-07-02 18:07:40 +02003973 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003974 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003975 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3976 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 if (r) {
3978 goto error;
3979 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003980 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003981 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003982 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003983 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003984 goto error;
3985 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003986 } else if (!strcmp(sub->name, "default")) {
3987 GETVAL(value, sub, "value");
3988
Radek Krejciac1a52c2016-09-15 14:42:40 +02003989 /* check for duplicity in case of configuration data,
3990 * in case of status data duplicities are allowed */
3991 if (llist->flags & LYS_CONFIG_W) {
3992 for (r = 0; r < llist->dflt_size; r++) {
3993 if (ly_strequal(llist->dflt[r], value, 1)) {
3994 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3995 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3996 goto error;
3997 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003998 }
3999 }
4000 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004002 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004003
Radek Krejcicbb473e2016-09-16 14:48:32 +02004004 /* finalize type parsing */
4005 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4006 llist->type.der = NULL;
4007 goto error;
4008 }
4009
Radek Krejcid5a5c282016-08-15 15:38:08 +02004010 if (llist->dflt_size && llist->min) {
Radek Krejci200bf712016-08-16 17:11:04 +02004011 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "leaf-list");
Radek Krejcid5a5c282016-08-15 15:38:08 +02004012 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
4013 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4014 goto error;
4015 }
4016
4017 /* check default value (if not defined, there still could be some restrictions
4018 * that need to be checked against a default value from a derived type) */
4019 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004020 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4021 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004022 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004023 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004024 }
4025
Michal Vasko508a50d2016-09-07 14:50:33 +02004026 /* check XPath dependencies */
4027 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4028 goto error;
4029 }
4030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004031 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004032
4033error:
4034
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004035 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004037 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004038}
4039
Michal Vasko0d343d12015-08-24 14:57:36 +02004040/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004041static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004042read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004043 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004044{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004045 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004046 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004048 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004049 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02004051 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004052 char *auxs;
4053 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004055 /* init */
4056 memset(&root, 0, sizeof root);
4057 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004059 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004060 if (!list) {
4061 LOGMEM;
4062 return NULL;
4063 }
Radek Krejci76512572015-08-04 09:47:08 +02004064 list->nodetype = LYS_LIST;
4065 list->prev = (struct lys_node *)list;
4066 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004067
Michal Vaskoe022a562016-09-27 14:24:15 +02004068 if (read_yin_common(module, parent, retval, yin,
4069 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
4070 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004071 goto error;
4072 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004073
Radek Krejcia9544502015-08-14 08:24:29 +02004074 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4075
Radek Krejcic189a952016-07-11 15:27:07 +02004076 /* insert the node into the schema tree */
4077 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4078 goto error;
4079 }
4080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004081 /* process list's specific children */
4082 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004083 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4084 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004085 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004086 continue;
4087 }
4088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004089 /* data statements */
4090 if (!strcmp(sub->name, "container") ||
4091 !strcmp(sub->name, "leaf-list") ||
4092 !strcmp(sub->name, "leaf") ||
4093 !strcmp(sub->name, "list") ||
4094 !strcmp(sub->name, "choice") ||
4095 !strcmp(sub->name, "uses") ||
4096 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004097 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004098 !strcmp(sub->name, "action") ||
4099 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004100 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004101 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103 /* array counters */
4104 } else if (!strcmp(sub->name, "key")) {
4105 /* check cardinality 0..1 */
4106 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004107 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004108 goto error;
4109 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004111 /* count the number of keys */
4112 GETVAL(value, sub, "value");
4113 key_str = value;
4114 while ((value = strpbrk(value, " \t\n"))) {
4115 list->keys_size++;
4116 while (isspace(*value)) {
4117 value++;
4118 }
4119 }
4120 list->keys_size++;
4121 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004122 if (!list->keys) {
4123 LOGMEM;
4124 goto error;
4125 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004126 } else if (!strcmp(sub->name, "unique")) {
4127 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004128 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004129 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004130 } else if (!strcmp(sub->name, "typedef")) {
4131 c_tpdf++;
4132 } else if (!strcmp(sub->name, "must")) {
4133 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004134 } else if (!strcmp(sub->name, "if-feature")) {
4135 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004137 /* optional stetments */
4138 } else if (!strcmp(sub->name, "ordered-by")) {
4139 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004140 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004141 goto error;
4142 }
4143 /* just checking the flags in llist is not sufficient, we would
4144 * allow multiple ordered-by statements with the "system" value
4145 */
4146 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004147
Radek Krejci1574a8d2015-08-03 14:16:52 +02004148 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4150 * state data
4151 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004152 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004153 continue;
4154 }
Radek Krejci345ad742015-06-03 11:04:18 +02004155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004156 GETVAL(value, sub, "value");
4157 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004158 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004159 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004160 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 goto error;
4162 }
4163 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004164 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004165 } else if (!strcmp(sub->name, "min-elements")) {
4166 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004167 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 goto error;
4169 }
4170 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 GETVAL(value, sub, "value");
4173 while (isspace(value[0])) {
4174 value++;
4175 }
Radek Krejci345ad742015-06-03 11:04:18 +02004176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177 /* convert it to uint32_t */
4178 errno = 0;
4179 auxs = NULL;
4180 val = strtoul(value, &auxs, 10);
4181 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004182 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183 goto error;
4184 }
4185 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004186 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004187 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4188 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004189 lyxml_free(module->ctx, sub);
4190 goto error;
4191 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004192 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004193 } else if (!strcmp(sub->name, "max-elements")) {
4194 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004195 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004196 goto error;
4197 }
4198 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004200 GETVAL(value, sub, "value");
4201 while (isspace(value[0])) {
4202 value++;
4203 }
Radek Krejci345ad742015-06-03 11:04:18 +02004204
Radek Krejci0d7b2472016-02-12 11:11:03 +01004205 if (!strcmp(value, "unbounded")) {
4206 list->max = 0;;
4207 } else {
4208 /* convert it to uint32_t */
4209 errno = 0;
4210 auxs = NULL;
4211 val = strtoul(value, &auxs, 10);
4212 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004213 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004214 goto error;
4215 }
4216 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004217 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004218 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4219 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004220 goto error;
4221 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004222 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004223 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004224 } else if (!strcmp(sub->name, "when")) {
4225 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004226 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004227 goto error;
4228 }
4229
4230 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004231 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004232 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004233 goto error;
4234 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004235 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004236 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004237 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004238 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004239 }
4240 }
Radek Krejci345ad742015-06-03 11:04:18 +02004241
Michal Vaskoe022a562016-09-27 14:24:15 +02004242 /* check - if list is configuration, key statement is mandatory
4243 * (but only if we are not in a grouping or augment, then the check is deferred) */
4244 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
4245 if (!node && (list->flags & LYS_CONFIG_W) && !key_str) {
4246 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004247 goto error;
4248 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004250 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4251 if (c_tpdf) {
4252 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004253 if (!list->tpdf) {
4254 LOGMEM;
4255 goto error;
4256 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004257 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004258 if (c_must) {
4259 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004260 if (!list->must) {
4261 LOGMEM;
4262 goto error;
4263 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004264 }
4265 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004266 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4267 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004268 LOGMEM;
4269 goto error;
4270 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004271 }
Radek Krejci73adb602015-07-02 18:07:40 +02004272 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004273 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004274 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4275 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 if (r) {
4277 goto error;
4278 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004279 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004280 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004281 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004282 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004283 goto error;
4284 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004285 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004286 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4287 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004288 if (r) {
4289 goto error;
4290 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004291 }
4292 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004294 /* last part - process data nodes */
4295 LY_TREE_FOR_SAFE(root.child, next, sub) {
4296 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004297 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004299 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004300 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004301 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004303 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004304 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004305 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004307 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004309 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004310 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004311 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004312 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004313 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004314 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004315 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004316 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004317 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004318 } else {
4319 LOGINT;
4320 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004322 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004323 goto error;
4324 }
Radek Krejci73adb602015-07-02 18:07:40 +02004325
Michal Vasko345da0a2015-12-02 10:35:55 +01004326 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004327 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004328
Radek Krejci461efb92016-02-12 15:52:18 +01004329 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004330 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004331 goto error;
4332 }
4333 } /* 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 +02004334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004335 /* process unique statements */
4336 if (c_uniq) {
4337 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004338 if (!list->unique) {
4339 LOGMEM;
4340 goto error;
4341 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004342
Radek Krejci461efb92016-02-12 15:52:18 +01004343 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4344 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4345 list->unique_size++;
4346 if (r) {
4347 goto error;
4348 }
4349
4350 lyxml_free(module->ctx, sub);
4351 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004353
Michal Vasko508a50d2016-09-07 14:50:33 +02004354 /* check XPath dependencies */
4355 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4356 goto error;
4357 }
4358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004359 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004360
4361error:
4362
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004363 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004365 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 }
4367 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004368 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004369 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004372}
4373
Michal Vasko0d343d12015-08-24 14:57:36 +02004374/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004375static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004376read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004377 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004378{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004379 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004380 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004381 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004382 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004383 const char *value;
4384 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004385 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004387 /* init */
4388 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004391 if (!cont) {
4392 LOGMEM;
4393 return NULL;
4394 }
Radek Krejci76512572015-08-04 09:47:08 +02004395 cont->nodetype = LYS_CONTAINER;
4396 cont->prev = (struct lys_node *)cont;
4397 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004398
Michal Vaskoe022a562016-09-27 14:24:15 +02004399 if (read_yin_common(module, parent, retval, yin,
4400 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
4401 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 goto error;
4403 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004404
Radek Krejcia9544502015-08-14 08:24:29 +02004405 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4406
Radek Krejcic189a952016-07-11 15:27:07 +02004407 /* insert the node into the schema tree */
4408 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4409 goto error;
4410 }
4411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004412 /* process container's specific children */
4413 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02004414 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004415 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004416 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004417 continue;
4418 }
4419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 if (!strcmp(sub->name, "presence")) {
4421 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004422 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 goto error;
4424 }
4425 GETVAL(value, sub, "value");
4426 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004427
Michal Vasko345da0a2015-12-02 10:35:55 +01004428 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004429 } else if (!strcmp(sub->name, "when")) {
4430 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004431 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004432 goto error;
4433 }
4434
4435 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004436 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004437 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004438 goto error;
4439 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004440 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004442 /* data statements */
4443 } else if (!strcmp(sub->name, "container") ||
4444 !strcmp(sub->name, "leaf-list") ||
4445 !strcmp(sub->name, "leaf") ||
4446 !strcmp(sub->name, "list") ||
4447 !strcmp(sub->name, "choice") ||
4448 !strcmp(sub->name, "uses") ||
4449 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004450 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004451 !strcmp(sub->name, "action") ||
4452 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004453 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004454 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004456 /* array counters */
4457 } else if (!strcmp(sub->name, "typedef")) {
4458 c_tpdf++;
4459 } else if (!strcmp(sub->name, "must")) {
4460 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004461 } else if (!strcmp(sub->name, "if-feature")) {
4462 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004464 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 }
4467 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4470 if (c_tpdf) {
4471 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004472 if (!cont->tpdf) {
4473 LOGMEM;
4474 goto error;
4475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 }
4477 if (c_must) {
4478 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004479 if (!cont->must) {
4480 LOGMEM;
4481 goto error;
4482 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004483 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004484 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004485 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4486 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004487 LOGMEM;
4488 goto error;
4489 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004490 }
Radek Krejci800af702015-06-02 13:46:01 +02004491
Radek Krejci73adb602015-07-02 18:07:40 +02004492 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004494 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4495 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 if (r) {
4497 goto error;
4498 }
4499 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004500 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4501 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004502 if (r) {
4503 goto error;
4504 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004505 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004506 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004507 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004508 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004509 goto error;
4510 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 /* last part - process data nodes */
4515 LY_TREE_FOR_SAFE(root.child, next, sub) {
4516 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004517 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004519 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004521 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004523 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004525 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004527 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004529 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004531 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004532 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004533 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004534 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004535 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004536 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004537 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004539 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 goto error;
4541 }
Radek Krejci73adb602015-07-02 18:07:40 +02004542
Michal Vasko345da0a2015-12-02 10:35:55 +01004543 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004545
Michal Vasko508a50d2016-09-07 14:50:33 +02004546 /* check XPath dependencies */
4547 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4548 goto error;
4549 }
4550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004551 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004552
4553error:
4554
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004555 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004557 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004561}
4562
Michal Vasko0d343d12015-08-24 14:57:36 +02004563/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004564static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004565read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004566 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004567{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004569 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004570 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004571 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 int r;
4573 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004575 /* init */
4576 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004579 if (!grp) {
4580 LOGMEM;
4581 return NULL;
4582 }
Radek Krejci76512572015-08-04 09:47:08 +02004583 grp->nodetype = LYS_GROUPING;
4584 grp->prev = (struct lys_node *)grp;
4585 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004586
Michal Vaskoe022a562016-09-27 14:24:15 +02004587 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 +02004588 goto error;
4589 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004590
Radek Krejcia9544502015-08-14 08:24:29 +02004591 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4592
Radek Krejcic189a952016-07-11 15:27:07 +02004593 /* insert the node into the schema tree */
4594 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4595 goto error;
4596 }
4597
Radek Krejci1d82ef62015-08-07 14:44:40 +02004598 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004599 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4600 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004601 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004602 continue;
4603 }
4604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 /* data statements */
4606 if (!strcmp(sub->name, "container") ||
4607 !strcmp(sub->name, "leaf-list") ||
4608 !strcmp(sub->name, "leaf") ||
4609 !strcmp(sub->name, "list") ||
4610 !strcmp(sub->name, "choice") ||
4611 !strcmp(sub->name, "uses") ||
4612 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004613 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02004614 !strcmp(sub->name, "action") ||
4615 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004616 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004617 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 /* array counters */
4620 } else if (!strcmp(sub->name, "typedef")) {
4621 c_tpdf++;
4622 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004623 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 goto error;
4625 }
4626 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4629 if (c_tpdf) {
4630 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004631 if (!grp->tpdf) {
4632 LOGMEM;
4633 goto error;
4634 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004636 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004637 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4638 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004639 if (r) {
4640 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004645 if (!root.child) {
4646 LOGWRN("Grouping \"%s\" without children.", retval->name);
4647 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 LY_TREE_FOR_SAFE(root.child, next, sub) {
4649 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004650 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004652 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004654 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004656 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004658 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004660 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004662 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004664 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004665 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004666 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004667 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004668 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02004669 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004670 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004672 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 goto error;
4674 }
Radek Krejci73adb602015-07-02 18:07:40 +02004675
Michal Vasko345da0a2015-12-02 10:35:55 +01004676 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004680
4681error:
4682
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004683 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004685 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004689}
4690
Michal Vasko0d343d12015-08-24 14:57:36 +02004691/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004692static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004693read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02004694 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004695{
Radek Krejcie0674f82015-06-15 13:58:51 +02004696 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004697 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004698 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004699 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004700 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004701 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004702
Radek Krejcie0674f82015-06-15 13:58:51 +02004703 /* init */
4704 memset(&root, 0, sizeof root);
4705
Michal Vasko38d01f72015-06-15 09:41:06 +02004706 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004707 if (!inout) {
4708 LOGMEM;
4709 return NULL;
4710 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004711 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004712
4713 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004714 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004715 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004716 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004717 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004718 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004719 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004720 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004721 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004722 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004723 }
4724
Radek Krejci76512572015-08-04 09:47:08 +02004725 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004726
Radek Krejci6a113852015-07-03 16:04:20 +02004727 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004728 goto error;
4729 }
4730
Radek Krejcia9544502015-08-14 08:24:29 +02004731 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4732
Radek Krejcic189a952016-07-11 15:27:07 +02004733 /* insert the node into the schema tree */
4734 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4735 goto error;
4736 }
4737
Michal Vasko38d01f72015-06-15 09:41:06 +02004738 /* data statements */
4739 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004740 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4741 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004742 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004743 continue;
4744 }
4745
Michal Vasko38d01f72015-06-15 09:41:06 +02004746 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 !strcmp(sub->name, "leaf-list") ||
4748 !strcmp(sub->name, "leaf") ||
4749 !strcmp(sub->name, "list") ||
4750 !strcmp(sub->name, "choice") ||
4751 !strcmp(sub->name, "uses") ||
4752 !strcmp(sub->name, "grouping") ||
4753 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004754 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004755 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004758 } else if (!strcmp(sub->name, "typedef")) {
4759 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004760
Radek Krejci1a31efe2016-07-29 11:04:16 +02004761 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004762 c_must++;
4763
Michal Vasko38d01f72015-06-15 09:41:06 +02004764 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004765 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004766 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004767 }
4768 }
4769
4770 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4771 if (c_tpdf) {
4772 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004773 if (!inout->tpdf) {
4774 LOGMEM;
4775 goto error;
4776 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004777 }
Radek Krejci19332802016-07-29 10:39:46 +02004778 if (c_must) {
4779 inout->must = calloc(c_must, sizeof *inout->must);
4780 if (!inout->must) {
4781 LOGMEM;
4782 goto error;
4783 }
4784 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004785
Radek Krejci73adb602015-07-02 18:07:40 +02004786 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004787 if (!strcmp(sub->name, "must")) {
4788 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4789 inout->must_size++;
4790 if (r) {
4791 goto error;
4792 }
4793 } else { /* typedef */
4794 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4795 inout->tpdf_size++;
4796 if (r) {
4797 goto error;
4798 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004799 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004800 }
4801
4802 /* last part - process data nodes */
4803 LY_TREE_FOR_SAFE(root.child, next, sub) {
4804 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004805 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004806 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004807 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004808 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004809 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004810 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004811 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004812 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004813 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004814 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004815 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004816 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004817 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004818 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004819 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004820 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004821 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004822 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004823 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004824 goto error;
4825 }
Radek Krejci73adb602015-07-02 18:07:40 +02004826
Michal Vasko345da0a2015-12-02 10:35:55 +01004827 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004828 }
4829
Michal Vasko508a50d2016-09-07 14:50:33 +02004830 /* check XPath dependencies */
4831 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4832 goto error;
4833 }
4834
Michal Vasko38d01f72015-06-15 09:41:06 +02004835 return retval;
4836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004838
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004839 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004840 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004841 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004842 }
4843
4844 return NULL;
4845}
4846
Michal Vasko0d343d12015-08-24 14:57:36 +02004847/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004848static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004849read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02004850 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004851{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004852 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004853 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004854 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004855 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004856 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004857 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004858
Michal Vasko6bb7fc12016-09-21 14:17:22 +02004859 if (parent && (module->version < 2)) {
4860 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "notification");
4861 return NULL;
4862 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004863
Michal Vaskoc6551b32015-06-16 10:51:43 +02004864 memset(&root, 0, sizeof root);
4865
Michal Vasko0ea41032015-06-16 08:53:55 +02004866 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004867 if (!notif) {
4868 LOGMEM;
4869 return NULL;
4870 }
Radek Krejci76512572015-08-04 09:47:08 +02004871 notif->nodetype = LYS_NOTIF;
4872 notif->prev = (struct lys_node *)notif;
4873 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004874
Radek Krejci6a113852015-07-03 16:04:20 +02004875 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004876 goto error;
4877 }
4878
Radek Krejcia9544502015-08-14 08:24:29 +02004879 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4880
Radek Krejcic189a952016-07-11 15:27:07 +02004881 /* insert the node into the schema tree */
4882 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4883 goto error;
4884 }
4885
Michal Vasko0ea41032015-06-16 08:53:55 +02004886 /* process rpc's specific children */
4887 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004888 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4889 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004890 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004891 continue;
4892 }
4893
Michal Vasko0ea41032015-06-16 08:53:55 +02004894 /* data statements */
4895 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 !strcmp(sub->name, "leaf-list") ||
4897 !strcmp(sub->name, "leaf") ||
4898 !strcmp(sub->name, "list") ||
4899 !strcmp(sub->name, "choice") ||
4900 !strcmp(sub->name, "uses") ||
4901 !strcmp(sub->name, "grouping") ||
4902 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004903 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004904 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004907 } else if (!strcmp(sub->name, "typedef")) {
4908 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004909 } else if (!strcmp(sub->name, "if-feature")) {
4910 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004911 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004912 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004913 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004914 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004915 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004916 }
4917 }
4918
4919 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4920 if (c_tpdf) {
4921 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004922 if (!notif->tpdf) {
4923 LOGMEM;
4924 goto error;
4925 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004926 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004927 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004928 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4929 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004930 LOGMEM;
4931 goto error;
4932 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004933 }
Radek Krejci19332802016-07-29 10:39:46 +02004934 if (c_must) {
4935 notif->must = calloc(c_must, sizeof *notif->must);
4936 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004937 LOGMEM;
4938 goto error;
4939 }
4940 }
4941
Radek Krejci73adb602015-07-02 18:07:40 +02004942 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004943 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004944 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4945 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004946 if (r) {
4947 goto error;
4948 }
Radek Krejci96299152016-06-22 10:17:50 +02004949 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004950 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004951 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004952 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004953 goto error;
4954 }
Radek Krejci19332802016-07-29 10:39:46 +02004955 } else if (!strcmp(sub->name, "must")) {
4956 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4957 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02004958 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004959 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004960 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004961 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004962 }
4963
4964 /* last part - process data nodes */
4965 LY_TREE_FOR_SAFE(root.child, next, sub) {
4966 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004967 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004968 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004969 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004970 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004971 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004972 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004973 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004974 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004975 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004976 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004977 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004978 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004979 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004980 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004981 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004982 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004983 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004984 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004985 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004986 goto error;
4987 }
Radek Krejci73adb602015-07-02 18:07:40 +02004988
Michal Vasko345da0a2015-12-02 10:35:55 +01004989 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004990 }
4991
Michal Vasko508a50d2016-09-07 14:50:33 +02004992 /* check XPath dependencies */
4993 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4994 goto error;
4995 }
4996
Michal Vasko0ea41032015-06-16 08:53:55 +02004997 return retval;
4998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005000
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005001 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005002 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005003 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005004 }
5005
5006 return NULL;
5007}
5008
Michal Vasko0d343d12015-08-24 14:57:36 +02005009/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005010static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005011read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005012 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005013{
Radek Krejcie0674f82015-06-15 13:58:51 +02005014 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005015 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005016 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005017 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005018 int r;
Pavol Vican3cb70c72016-09-05 11:32:52 +02005019 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005020
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005021 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005022 if (module->version < 2) {
Michal Vaskobb174852016-07-25 11:00:21 +02005023 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
5024 return NULL;
5025 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005026 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005027 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005028 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
5029 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
5030 return NULL;
5031 }
5032 }
5033 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005034
Radek Krejcie0674f82015-06-15 13:58:51 +02005035 /* init */
5036 memset(&root, 0, sizeof root);
5037
Michal Vasko38d01f72015-06-15 09:41:06 +02005038 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005039 if (!rpc) {
5040 LOGMEM;
5041 return NULL;
5042 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005043 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005044 rpc->prev = (struct lys_node *)rpc;
5045 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005046
Radek Krejci6a113852015-07-03 16:04:20 +02005047 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005048 goto error;
5049 }
5050
Radek Krejcia9544502015-08-14 08:24:29 +02005051 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5052
Radek Krejcic189a952016-07-11 15:27:07 +02005053 /* insert the node into the schema tree */
5054 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5055 goto error;
5056 }
5057
Michal Vasko38d01f72015-06-15 09:41:06 +02005058 /* process rpc's specific children */
5059 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005060 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5061 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005062 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005063 continue;
5064 }
5065
Michal Vasko38d01f72015-06-15 09:41:06 +02005066 if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005067 if (c_input) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005068 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005069 goto error;
5070 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005071 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005072 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005073 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005074 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005075 if (c_output) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005076 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005077 goto error;
5078 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005079 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005080 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005081 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005083 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005084 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005085 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005086 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005088 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005089 } else if (!strcmp(sub->name, "typedef")) {
5090 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005091 } else if (!strcmp(sub->name, "if-feature")) {
5092 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005093 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005094 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005095 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005096 }
5097 }
5098
5099 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5100 if (c_tpdf) {
5101 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005102 if (!rpc->tpdf) {
5103 LOGMEM;
5104 goto error;
5105 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005106 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005107 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005108 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5109 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005110 LOGMEM;
5111 goto error;
5112 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005113 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005114
Radek Krejci73adb602015-07-02 18:07:40 +02005115 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005116 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005117 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5118 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005119 if (r) {
5120 goto error;
5121 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005122 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005123 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005124 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005125 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005126 goto error;
5127 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005128 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005129 }
5130
5131 /* last part - process data nodes */
5132 LY_TREE_FOR_SAFE(root.child, next, sub) {
5133 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005134 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005135 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005136 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005137 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005138 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005139 goto error;
5140 }
Radek Krejci73adb602015-07-02 18:07:40 +02005141
Michal Vasko345da0a2015-12-02 10:35:55 +01005142 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005143 }
5144
Michal Vasko38d01f72015-06-15 09:41:06 +02005145 return retval;
5146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005147error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005148
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005149 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005150 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005151 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005152 }
5153
5154 return NULL;
5155}
5156
Michal Vasko0d343d12015-08-24 14:57:36 +02005157/* logs directly
5158 *
Radek Krejci74705112015-06-05 10:25:44 +02005159 * resolve - referenced grouping should be bounded to the namespace (resolved)
5160 * only when uses does not appear in grouping. In a case of grouping's uses,
5161 * we just get information but we do not apply augment or refine to it.
5162 */
Radek Krejci76512572015-08-04 09:47:08 +02005163static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005164read_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 +02005165{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005166 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005167 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005168 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005170 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005174 if (!uses) {
5175 LOGMEM;
5176 return NULL;
5177 }
Radek Krejci76512572015-08-04 09:47:08 +02005178 uses->nodetype = LYS_USES;
5179 uses->prev = (struct lys_node *)uses;
5180 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005181
Radek Krejcia9544502015-08-14 08:24:29 +02005182 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005184
Michal Vaskoe0c59842015-09-24 13:52:20 +02005185 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02005186 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005187 goto error;
5188 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005189
Radek Krejcia9544502015-08-14 08:24:29 +02005190 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5191
Radek Krejcic189a952016-07-11 15:27:07 +02005192 /* insert the node into the schema tree */
5193 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5194 goto error;
5195 }
5196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005198 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005199 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5200 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005201 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005202 continue;
5203 }
5204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 if (!strcmp(sub->name, "refine")) {
5206 c_ref++;
5207 } else if (!strcmp(sub->name, "augment")) {
5208 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005209 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005210 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005211 } else if (!strcmp(sub->name, "when")) {
5212 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005213 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005214 goto error;
5215 }
5216
5217 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005218 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005219 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005220 goto error;
5221 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005222 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005224 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005226 }
5227 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005229 /* process properties with cardinality 0..n */
5230 if (c_ref) {
5231 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005232 if (!uses->refine) {
5233 LOGMEM;
5234 goto error;
5235 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005236 }
5237 if (c_aug) {
5238 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005239 if (!uses->augment) {
5240 LOGMEM;
5241 goto error;
5242 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005244 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005245 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5246 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005247 LOGMEM;
5248 goto error;
5249 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005250 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005251
Radek Krejcia9544502015-08-14 08:24:29 +02005252 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005254 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005255 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005256 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005257 goto error;
5258 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005259 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005260 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5261 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005262 if (r) {
5263 goto error;
5264 }
5265 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005266 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005267 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005268 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005269 goto error;
5270 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 }
5272 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005273
Radek Krejci48464ed2016-03-17 15:44:09 +01005274 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005275 goto error;
5276 }
Radek Krejci74705112015-06-05 10:25:44 +02005277
Michal Vasko508a50d2016-09-07 14:50:33 +02005278 /* check XPath dependencies */
5279 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5280 goto error;
5281 }
5282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005283 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005284
5285error:
5286
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005287 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005290}
5291
Michal Vasko0d343d12015-08-24 14:57:36 +02005292/* logs directly
5293 *
5294 * common code for yin_read_module() and yin_read_submodule()
5295 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296static int
Radek Krejcic071c542016-01-27 14:57:51 +01005297read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5298 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005299{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005301 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005302 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005303 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005304 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005305 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005306 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005307 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005308 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005309 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02005310 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 +02005311
Radek Krejcic071c542016-01-27 14:57:51 +01005312 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005313 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005315 /* init */
5316 memset(&root, 0, sizeof root);
5317 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005318 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02005319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005320 /*
5321 * in the first run, we process elements with cardinality of 1 or 0..1 and
5322 * count elements with cardinality 0..n. Data elements (choices, containers,
5323 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5324 * need have all top-level and groupings already prepared at that time. In
5325 * the middle loop, we process other elements with carinality of 0..n since
5326 * we need to allocate arrays to store them.
5327 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005328 LY_TREE_FOR_SAFE(yin->child, next, child) {
5329 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005330 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005331 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005332 continue;
5333 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005334
Radek Krejcic071c542016-01-27 14:57:51 +01005335 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005336 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005337 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005338 goto error;
5339 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005340 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005341 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005342 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005343 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005345 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 goto error;
5347 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005348 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005349 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 goto error;
5351 }
5352 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005353 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005354 } else if (submodule && !strcmp(child->name, "belongs-to")) {
5355 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005356 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 goto error;
5358 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005359 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005360 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005361 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005362 goto error;
5363 }
Radek Krejcif3886932015-06-04 17:36:06 +02005364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005365 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005366 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005367 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005368 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005369 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005370 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005371 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005372 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005373 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005374 goto error;
5375 }
5376 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005377 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005378 /* check here differs from a generic prefix check, since this prefix
5379 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005380 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005381 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005382 goto error;
5383 }
Radek Krejcic071c542016-01-27 14:57:51 +01005384 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005386 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005387 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005388
5389 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005390 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005391 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005392 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005393 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005394 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005395 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005396 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005398 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005399 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005400 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005401 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005402 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005403 lyxml_unlink_elem(ctx, child, 2);
5404 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005405
Radek Krejci1d82ef62015-08-07 14:44:40 +02005406 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005407 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005408 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02005409 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005411 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005412 } else if (!strcmp(child->name, "container") ||
5413 !strcmp(child->name, "leaf-list") ||
5414 !strcmp(child->name, "leaf") ||
5415 !strcmp(child->name, "list") ||
5416 !strcmp(child->name, "choice") ||
5417 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005418 !strcmp(child->name, "anyxml") ||
5419 !strcmp(child->name, "rpc") ||
5420 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005421 lyxml_unlink_elem(ctx, child, 2);
5422 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005423
Radek Krejci1d82ef62015-08-07 14:44:40 +02005424 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005426 lyxml_unlink_elem(ctx, child, 2);
5427 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005429 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005430 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005431 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005432 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005433 goto error;
5434 }
Radek Krejcic071c542016-01-27 14:57:51 +01005435 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005436 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005437 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005438 goto error;
5439 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005440 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005441 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005442 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 goto error;
5444 }
Radek Krejcic071c542016-01-27 14:57:51 +01005445 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005446 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005447 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005448 goto error;
5449 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005450 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005451 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005452 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 goto error;
5454 }
Radek Krejcic071c542016-01-27 14:57:51 +01005455 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005456 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005457 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005458 goto error;
5459 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005460 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005461 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005462 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005463 goto error;
5464 }
Radek Krejcic071c542016-01-27 14:57:51 +01005465 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005466 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005467 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005468 goto error;
5469 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005470 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005471 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005472 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005473 goto error;
5474 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005475 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005476 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005477 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005478 goto error;
5479 }
Radek Krejcic071c542016-01-27 14:57:51 +01005480 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005481 if (!strcmp(value, "1")) {
5482 if (submodule) {
5483 if (module->version > 1) {
5484 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5485 goto error;
5486 }
5487 } else {
5488 module->version = 1;
5489 }
5490 } else {
5491 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005492 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005493 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5494 goto error;
5495 }
5496 } else {
5497 module->version = 2;
5498 }
5499 }
5500
Michal Vasko345da0a2015-12-02 10:35:55 +01005501 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005502
Radek Krejci1d82ef62015-08-07 14:44:40 +02005503 } else if (!strcmp(child->name, "extension")) {
5504 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005505
Radek Krejci3d468122015-10-02 13:36:12 +02005506 /* we have the following supported (hardcoded) extensions: */
5507 /* ietf-netconf's get-filter-element-attributes */
5508 if (!strcmp(module->ns, LY_NSNC) &&
5509 !strcmp(value, "get-filter-element-attributes")) {
5510 LOGDBG("NETCONF filter extension found");
5511 /* NACM's default-deny-write and default-deny-all */
5512 } else if (!strcmp(module->ns, LY_NSNACM) &&
5513 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5514 LOGDBG("NACM extension found");
5515 /* other extensions are not supported, so inform about such an extension */
5516 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005517 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005518 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005519 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005520 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005521 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005522 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005523 }
5524 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005525
Radek Krejcic071c542016-01-27 14:57:51 +01005526 /* check for mandatory statements */
5527 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005528 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005529 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005530 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005531 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005532 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005533 goto error;
5534 }
5535 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005536 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005537 goto error;
5538 }
5539 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005541 /* allocate arrays for elements with cardinality of 0..n */
5542 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005543 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5544 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005545 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005546 LOGMEM;
5547 goto error;
5548 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005549 /* set stop block for possible realloc */
5550 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005551 }
5552 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005553 trg->rev = calloc(c_rev, sizeof *trg->rev);
5554 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005555 LOGMEM;
5556 goto error;
5557 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005558 }
5559 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005560 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5561 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005562 LOGMEM;
5563 goto error;
5564 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005565 }
5566 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005567 trg->ident = calloc(c_ident, sizeof *trg->ident);
5568 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005569 LOGMEM;
5570 goto error;
5571 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005572 }
5573 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005574 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5575 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005576 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005577 LOGMEM;
5578 goto error;
5579 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005580 /* set stop block for possible realloc */
5581 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005582 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005583 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005584 trg->augment = calloc(c_aug, sizeof *trg->augment);
5585 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005586 LOGMEM;
5587 goto error;
5588 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005589 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005590 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005591 trg->features = calloc(c_ftrs, sizeof *trg->features);
5592 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005593 LOGMEM;
5594 goto error;
5595 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005596 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005597 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005598 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5599 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005600 LOGMEM;
5601 goto error;
5602 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005603 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005604
Michal Vasko2f7925f2015-10-21 15:06:56 +02005605 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5606 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005607 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005608 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5609 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 if (r) {
5611 goto error;
5612 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005613
Radek Krejci1d82ef62015-08-07 14:44:40 +02005614 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005615 memset(&inc, 0, sizeof inc);
5616 /* 1) pass module, not trg, since we want to pass the main module
5617 * 2) we cannot pass directly the structure in the array since
5618 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01005619 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005620 if (!r) {
5621 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02005622 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
5623 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005624 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005625 goto error;
5626 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005627
Radek Krejci1d82ef62015-08-07 14:44:40 +02005628 } else if (!strcmp(child->name, "revision")) {
5629 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005630 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005631 goto error;
5632 }
Radek Krejcic071c542016-01-27 14:57:51 +01005633 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005634 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005635 for (i = 0; i < trg->rev_size; i++) {
5636 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005637 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5638 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005639 }
5640 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005641
Radek Krejci1d82ef62015-08-07 14:44:40 +02005642 LY_TREE_FOR(child->child, child2) {
5643 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005644 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005645 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005646 goto error;
5647 }
Radek Krejcic071c542016-01-27 14:57:51 +01005648 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5649 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005650 goto error;
5651 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005652 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005653 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005654 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005655 goto error;
5656 }
Radek Krejcic071c542016-01-27 14:57:51 +01005657 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5658 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005659 goto error;
5660 }
5661 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005662 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005663 goto error;
5664 }
5665 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005667 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005668 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005670 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005671 if (!value) {
5672 LOGMEM;
5673 goto error;
5674 }
Radek Krejcic071c542016-01-27 14:57:51 +01005675 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5676 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005677 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005678
Radek Krejci749190d2016-02-18 16:26:25 +01005679 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005680 value = trg->rev[0].dsc;
5681 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5682 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005683 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005684
Radek Krejci749190d2016-02-18 16:26:25 +01005685 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005686 value = trg->rev[0].ref;
5687 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5688 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005689 }
5690 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005691
Radek Krejcic071c542016-01-27 14:57:51 +01005692 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005693
Radek Krejci1d82ef62015-08-07 14:44:40 +02005694 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005695 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5696 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005697 if (r) {
5698 goto error;
5699 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005700
Radek Krejci1d82ef62015-08-07 14:44:40 +02005701 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005702 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5703 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005704 if (r) {
5705 goto error;
5706 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005707
Radek Krejci1d82ef62015-08-07 14:44:40 +02005708 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005709 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5710 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005711 if (r) {
5712 goto error;
5713 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005714
Radek Krejci1d82ef62015-08-07 14:44:40 +02005715 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005716 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5717 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005718 if (r) {
5719 goto error;
5720 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005721 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005722 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005723
Radek Krejcib8f98c12016-06-24 10:30:46 +02005724 if (!submodule) {
5725 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005726 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005727 if (module->inc_size) {
5728 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5729 if (!module->inc) {
5730 LOGMEM;
5731 goto error;
5732 }
5733 }
5734 if (module->imp_size) {
5735 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5736 if (!module->imp) {
5737 LOGMEM;
5738 goto error;
5739 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005740 }
5741 }
Radek Krejcic071c542016-01-27 14:57:51 +01005742
Radek Krejcif5be10f2015-06-16 13:29:36 +02005743 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005744 * refer to them. Submodule's data nodes are stored in the
5745 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005746 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005747 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005748 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005749 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005750 goto error;
5751 }
Radek Krejci74705112015-06-05 10:25:44 +02005752
Michal Vasko345da0a2015-12-02 10:35:55 +01005753 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005754 }
Radek Krejci74705112015-06-05 10:25:44 +02005755
Radek Krejcif5be10f2015-06-16 13:29:36 +02005756 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005757 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005758
Radek Krejci1d82ef62015-08-07 14:44:40 +02005759 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005760 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005761 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005762 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005763 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005764 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005765 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005766 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005767 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005768 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005769 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005770 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005771 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02005772 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
5773 } else if (!strcmp(child->name, "anydata")) {
5774 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005775 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005776 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005777 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005778 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005779 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005780 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005781 goto error;
5782 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005783
Michal Vasko345da0a2015-12-02 10:35:55 +01005784 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005785 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005786
Michal Vasko2f7925f2015-10-21 15:06:56 +02005787 /* ... and finally augments (last, so we can augment our data, for instance) */
5788 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005789 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5790 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005791
Michal Vasko2f7925f2015-10-21 15:06:56 +02005792 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005793 goto error;
5794 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005795 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005796 }
5797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005798 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005799
5800error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005801 /* cleanup */
5802 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005803 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005804 }
5805 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005806 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005807 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005808 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005809 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005810 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005812 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005813}
5814
Michal Vasko0d343d12015-08-24 14:57:36 +02005815/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005816struct lys_submodule *
5817yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005818{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005819 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005820 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005821 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005822
Michal Vasko5a721fd2016-02-16 12:16:48 +01005823 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005824
Radek Krejci722b0072016-02-01 17:09:45 +01005825 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005826 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005827 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005828 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005830 /* check root element */
5831 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005832 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005833 goto error;
5834 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005836 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005837 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005838 goto error;
5839 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005840
Michal Vasko5a721fd2016-02-16 12:16:48 +01005841 submodule = calloc(1, sizeof *submodule);
5842 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005843 LOGMEM;
5844 goto error;
5845 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005846
Michal Vasko5a721fd2016-02-16 12:16:48 +01005847 submodule->ctx = module->ctx;
5848 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5849 submodule->type = 1;
5850 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005851
Michal Vasko5a721fd2016-02-16 12:16:48 +01005852 LOGVRB("Reading submodule \"%s\".", submodule->name);
5853 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005854 goto error;
5855 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005857 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005858 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005859
Michal Vasko5a721fd2016-02-16 12:16:48 +01005860 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005861 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005862
5863error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005864 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005865 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005866 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005867
Michal Vasko5a721fd2016-02-16 12:16:48 +01005868 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005869 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005870 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005871 }
5872
Michal Vasko5a721fd2016-02-16 12:16:48 +01005873 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005874
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005875 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5876 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005877 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005878 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005879}
5880
Michal Vasko0d343d12015-08-24 14:57:36 +02005881/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005882struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005883yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005884{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005885 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005886 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005887 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005888 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005889
Radek Krejcic071c542016-01-27 14:57:51 +01005890 unres = calloc(1, sizeof *unres);
5891 if (!unres) {
5892 LOGMEM;
5893 return NULL;
5894 }
5895
Radek Krejci722b0072016-02-01 17:09:45 +01005896 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005897 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005898 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005899 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005901 /* check root element */
5902 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005903 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02005904 if (ly_strequal("submodule", yin->name, 0)) {
5905 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
5906 "Submodules are parsed automatically as includes to the main module, do not parse them separately.");
5907 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005908 goto error;
5909 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005911 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005912 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005913 goto error;
5914 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005916 module = calloc(1, sizeof *module);
5917 if (!module) {
5918 LOGMEM;
5919 goto error;
5920 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005922 module->ctx = ctx;
5923 module->name = lydict_insert(ctx, value, strlen(value));
5924 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005925 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005926
Michal Vasko9f258e42016-02-11 11:36:27 +01005927 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005928 if (read_sub_module(module, NULL, yin, unres)) {
5929 goto error;
5930 }
5931
5932 /* resolve rest of unres items */
5933 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005934 goto error;
5935 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005936
Radek Krejciff4874d2016-03-07 12:30:50 +01005937 if (revision) {
5938 /* check revision of the parsed model */
5939 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005940 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5941 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005942 goto error;
5943 }
5944 }
5945
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005946 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005947 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005948 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005949
Radek Krejci27fe55e2016-09-13 17:13:35 +02005950 if (module->deviation_size && !module->implemented) {
5951 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
5952 /* deviations always causes target to be made implemented,
5953 * but augents and leafrefs not, so we have to apply them now */
5954 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02005955 goto error;
5956 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005957 }
5958
Michal Vasko345da0a2015-12-02 10:35:55 +01005959 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005960 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005961 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005962 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005963
5964error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005965 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005966 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005967 unres_schema_free(module, &unres);
5968
5969 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005970 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005971 return NULL;
5972 }
5973
5974 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005975
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005976 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005977 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005978 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005979}