blob: 49352487c6422d36fd0a9422bcbf7605243f8617 [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 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001048 }
Radek Krejci742be352016-07-17 12:18:54 +02001049 }
1050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 break;
1052
1053 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001054 /* RFC 6020 9.4.4 - length */
1055 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001056 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001057 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001058 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1059 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001060 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001061 continue;
1062 }
1063
Radek Krejci3733a802015-06-19 13:43:21 +02001064 if (!strcmp(node->name, "length")) {
1065 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001066 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001067 goto error;
1068 }
1069
1070 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001071 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001072 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001073 goto error;
1074 }
1075 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001076 if (!type->info.str.length) {
1077 LOGMEM;
1078 goto error;
1079 }
Radek Krejci3733a802015-06-19 13:43:21 +02001080 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1081
Radek Krejci5fbc9162015-06-19 14:11:11 +02001082 /* get possible sub-statements */
1083 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001084 goto error;
1085 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001086 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001087 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001088 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001089 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001090 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001091 goto error;
1092 }
1093 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001094 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001095 if (i) {
1096 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001097 if (!type->info.str.patterns) {
1098 LOGMEM;
1099 goto error;
1100 }
Radek Krejci73adb602015-07-02 18:07:40 +02001101 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001102 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001103 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001104 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001105 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001106 goto error;
1107 }
Michal Vasko69068852015-07-13 14:34:31 +02001108
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001109 modifier = 0x06; /* ACK */
1110 name = NULL;
1111 LY_TREE_FOR_SAFE(node->child, next2, child) {
1112 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1113 /* garbage */
1114 lyxml_free(module->ctx, child);
1115 continue;
1116 }
1117
1118 if (module->version >= 2 && !strcmp(child->name, "modifier")) {
1119 if (name) {
1120 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1121 goto error;
1122 }
1123
1124 GETVAL(name, child, "value");
1125 if (!strcmp(name, "invert-match")) {
1126 modifier = 0x15; /* NACK */
1127 } else {
1128 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1129 goto error;
1130 }
1131 lyxml_free(module->ctx, child);
1132 }
1133 }
1134
1135 len = strlen(value);
1136 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1137 buf[0] = modifier;
1138 strcpy(&buf[1], value);
1139
1140 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001141
1142 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +01001143 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +02001144 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001145 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001146 goto error;
1147 }
Radek Krejci73adb602015-07-02 18:07:40 +02001148 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001149 }
1150 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151 break;
1152
1153 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001154 /* RFC 6020 7.4 - type */
1155 /* count number of types in union */
1156 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001157 LY_TREE_FOR_SAFE(yin->child, next, node) {
1158 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1159 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001160 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001161 continue;
1162 }
1163
Radek Krejcie4c366b2015-07-02 10:11:31 +02001164 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001165 if (type->der->type.der) {
1166 /* type can be a substatement only in "union" type, not in derived types */
1167 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1168 goto error;
1169 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001170 i++;
1171 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001172 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001173 goto error;
1174 }
1175 }
1176
Radek Krejci038d5d92016-09-12 15:07:15 +02001177 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001178 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001179 goto error;
1180 }
1181
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001182 /* inherit instid presence information */
1183 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1184 type->info.uni.has_ptr_type = 1;
1185 }
1186
Radek Krejcie4c366b2015-07-02 10:11:31 +02001187 /* 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 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001210
1211 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1212 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1213 type->info.uni.has_ptr_type = 1;
1214 }
Michal Vasko88c29542015-11-27 14:57:53 +01001215 }
1216 if (rc) {
1217 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1218 for (i = 0; i < type->info.uni.count; ++i) {
1219 lys_type_free(module->ctx, &type->info.uni.types[i]);
1220 }
1221 free(type->info.uni.types);
1222 type->info.uni.types = NULL;
1223 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001224 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001225 type->der = NULL;
1226 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001227
1228 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001229 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001230 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001231 goto error;
1232 }
Michal Vasko88c29542015-11-27 14:57:53 +01001233 }
1234 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001235
Michal Vasko88c29542015-11-27 14:57:53 +01001236 case LY_TYPE_BOOL:
1237 case LY_TYPE_EMPTY:
1238 /* no sub-statement allowed */
1239 LY_TREE_FOR(yin->child, node) {
1240 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001241 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001242 goto error;
1243 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001244 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001245 break;
1246
1247 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001248 LOGINT;
1249 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001250 }
1251
1252 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001253
1254error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001255 if (type->module_name) {
1256 lydict_remove(module->ctx, type->module_name);
1257 type->module_name = NULL;
1258 }
1259 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001260}
1261
Michal Vasko0d343d12015-08-24 14:57:36 +02001262/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001263static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001264fill_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 +02001265{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001267 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +01001268 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001270 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001271 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 goto error;
1273 }
1274 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001276 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001277 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 goto error;
1279 }
Radek Krejcieac35532015-05-31 19:09:15 +02001280
Michal Vasko88c29542015-11-27 14:57:53 +01001281 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001282 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1283 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001284 continue;
1285 }
1286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001287 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001288 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001289 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001290 goto error;
1291 }
Michal Vasko88c29542015-11-27 14:57:53 +01001292 /* HACK for unres */
1293 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001294 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001295 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001296 goto error;
1297 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001298 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001299 } else if (!strcmp(node->name, "default")) {
1300 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001301 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302 goto error;
1303 }
1304 GETVAL(value, node, "value");
1305 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1306 } else if (!strcmp(node->name, "units")) {
1307 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001308 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001309 goto error;
1310 }
1311 GETVAL(value, node, "name");
1312 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1313 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001314 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001315 goto error;
1316 }
1317 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001319 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001320 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001321 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 goto error;
1323 }
Radek Krejcieac35532015-05-31 19:09:15 +02001324
Michal Vasko478c4652016-07-21 12:55:01 +02001325 /* check default value (if not defined, there still could be some restrictions
1326 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01001327 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 +02001328 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001331 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001332
1333error:
1334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001335 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001336}
1337
Michal Vasko0d343d12015-08-24 14:57:36 +02001338/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001339static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001340fill_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 +02001341{
1342 const char *value;
1343 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001344 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001345
Radek Krejcib05774c2015-06-18 13:52:59 +02001346 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001347 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001348 goto error;
1349 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001350 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001351 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001352
Radek Krejci76512572015-08-04 09:47:08 +02001353 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001354 goto error;
1355 }
1356
1357 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001358 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1359 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001360 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001361 continue;
1362 }
1363
Radek Krejci3cf9e222015-06-18 11:37:50 +02001364 if (!strcmp(child->name, "if-feature")) {
1365 c++;
1366 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001367 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001368 goto error;
1369 }
1370 }
1371
1372 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001373 f->iffeature = calloc(c, sizeof *f->iffeature);
1374 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001375 LOGMEM;
1376 goto error;
1377 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001378 }
Radek Krejci73adb602015-07-02 18:07:40 +02001379 LY_TREE_FOR(yin->child, child) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001380 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001381 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001382 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001383 goto error;
1384 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001385 }
1386
Radek Krejcic79c6b12016-07-26 15:11:49 +02001387 /* check for circular dependencies */
1388 if (f->iffeature_size) {
1389 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1390 goto error;
1391 }
1392 }
1393
Radek Krejci3cf9e222015-06-18 11:37:50 +02001394 return EXIT_SUCCESS;
1395
1396error:
1397
1398 return EXIT_FAILURE;
1399}
1400
Michal Vasko0d343d12015-08-24 14:57:36 +02001401/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001402static int
Radek Krejcib8048692015-08-05 13:36:34 +02001403fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001404{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001407 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001408 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001409 if (!must->expr) {
1410 goto error;
1411 }
Radek Krejci800af702015-06-02 13:46:01 +02001412
Radek Krejci41726f92015-06-19 13:11:05 +02001413 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001414
Michal Vasko77dc5652016-02-15 12:32:42 +01001415error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001416 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001417}
1418
Radek Krejci581ce772015-11-10 17:22:40 +01001419static int
Michal Vasko88c29542015-11-27 14:57:53 +01001420fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1421 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001422{
1423 int i, j;
1424 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001425 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001426
1427 /* get unique value (list of leafs supposed to be unique */
1428 GETVAL(value, yin, "tag");
1429
1430 /* count the number of unique leafs in the value */
1431 vaux = value;
1432 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001433 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001434 while (isspace(*vaux)) {
1435 vaux++;
1436 }
1437 }
1438 unique->expr_size++;
1439 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001440 if (!unique->expr) {
1441 LOGMEM;
1442 goto error;
1443 }
Radek Krejci581ce772015-11-10 17:22:40 +01001444
1445 for (i = 0; i < unique->expr_size; i++) {
1446 vaux = strpbrk(value, " \t\n");
1447 if (!vaux) {
1448 /* the last token, lydict_insert() will count its size on its own */
1449 vaux = value;
1450 }
1451
1452 /* store token into unique structure */
1453 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1454
1455 /* check that the expression does not repeat */
1456 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001457 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001458 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1459 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001460 goto error;
1461 }
1462 }
1463
1464 /* try to resolve leaf */
1465 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001466 unique_info = malloc(sizeof *unique_info);
1467 unique_info->list = parent;
1468 unique_info->expr = unique->expr[i];
1469 unique_info->trg_type = &unique->trg_type;
1470 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001471 goto error;
1472 }
Radek Krejci581ce772015-11-10 17:22:40 +01001473 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001474 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001475 goto error;
1476 }
1477 }
1478
1479 /* move to next token */
1480 value = vaux;
1481 while(isspace(*value)) {
1482 value++;
1483 }
1484 }
1485
1486 return EXIT_SUCCESS;
1487
1488error:
1489 return EXIT_FAILURE;
1490}
1491
Michal Vasko0d343d12015-08-24 14:57:36 +02001492/* logs directly
1493 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001494 * type: 0 - min, 1 - max
1495 */
1496static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001497deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001498{
1499 const char *value;
1500 char *endptr;
1501 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001502 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001503
Michal Vaskof7e57d52016-03-07 11:31:09 +01001504 /* del min/max is forbidden */
1505 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001506 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001507 goto error;
1508 }
1509
Radek Krejcieb00f512015-07-01 16:44:58 +02001510 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001511 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001512 max = &((struct lys_node_leaflist *)target)->max;
1513 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001514 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001515 max = &((struct lys_node_list *)target)->max;
1516 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001517 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001518 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1519 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001520 goto error;
1521 }
1522
1523 GETVAL(value, node, "value");
1524 while (isspace(value[0])) {
1525 value++;
1526 }
1527
Radek Krejci0d7b2472016-02-12 11:11:03 +01001528 if (type && !strcmp(value, "unbounded")) {
1529 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001530 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001531 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001533 /* convert it to uint32_t */
1534 errno = 0;
1535 endptr = NULL;
1536 val = strtoul(value, &endptr, 10);
1537 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001538 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001539 goto error;
1540 }
1541 if (type) {
1542 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001543 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001544 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001545 } else {
1546 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001547 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001548 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001549 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 }
1551
1552 if (d->mod == LY_DEVIATE_ADD) {
1553 /* check that there is no current value */
1554 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001555 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1556 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001557 goto error;
1558 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001559 } else if (d->mod == LY_DEVIATE_RPL) {
1560 /* unfortunately, there is no way to check reliably that there
1561 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 }
1563
Michal Vaskof7e57d52016-03-07 11:31:09 +01001564 /* add (already checked) and replace */
1565 /* set new value specified in deviation */
1566 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001567
Pavol Vican09adcc32016-08-25 10:51:36 +02001568 /* check min-elements is smaller than max-elements */
1569 if (*max && *min > *max) {
1570 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001571 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001572 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1573 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001574 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001575 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1576 }
1577 goto error;
1578 }
1579
Radek Krejcieb00f512015-07-01 16:44:58 +02001580 return EXIT_SUCCESS;
1581
1582error:
1583
1584 return EXIT_FAILURE;
1585}
1586
Michal Vasko0d343d12015-08-24 14:57:36 +02001587/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001588static int
Michal Vasko88c29542015-11-27 14:57:53 +01001589fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1590 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001591{
1592 const char *value, **stritem;
1593 struct lyxml_elem *next, *child, *develem;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001594 int c_dev = 0, c_must, c_uniq, c_dflt;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001595 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001596 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001597 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001598 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001599 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001600 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001601 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001602 struct lys_node_leaf *leaf = NULL;
1603 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001604 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001605 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001606 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001607 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001608 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001609 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001610 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02001611
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001612 ctx = module->ctx;
1613
Radek Krejcieb00f512015-07-01 16:44:58 +02001614 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001615 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001616 if (!dev->target_name) {
1617 goto error;
1618 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001619
1620 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001621 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01001622 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001623 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001624 goto error;
1625 }
Radek Krejcic4283442016-04-22 09:19:27 +02001626 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001627 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1628 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001629 goto error;
1630 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001631
1632 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001633 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1634 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001635 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001636 continue;
1637 }
1638
Radek Krejcieb00f512015-07-01 16:44:58 +02001639 if (!strcmp(child->name, "description")) {
1640 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001641 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 goto error;
1643 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001644 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 if (!dev->dsc) {
1646 goto error;
1647 }
1648 } else if (!strcmp(child->name, "reference")) {
1649 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001650 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001651 goto error;
1652 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001653 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001654 if (!dev->ref) {
1655 goto error;
1656 }
1657 } else if (!strcmp(child->name, "deviate")) {
1658 c_dev++;
1659
Michal Vasko345da0a2015-12-02 10:35:55 +01001660 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001661 * further processed later
1662 */
1663 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001664
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001666 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 goto error;
1668 }
1669
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001670 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 }
1672
1673 if (c_dev) {
1674 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001675 if (!dev->deviate) {
1676 LOGMEM;
1677 goto error;
1678 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001679 } else {
1680 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1681 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 }
1683
1684 LY_TREE_FOR(yin->child, develem) {
1685 /* init */
1686 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001687 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001688 c_must = 0;
1689 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001690 c_dflt = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001691
1692 /* get deviation type */
1693 GETVAL(value, develem, "value");
1694 if (!strcmp(value, "not-supported")) {
1695 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1696 /* no property expected in this case */
1697 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001698 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001699 goto error;
1700 }
1701
Radek Krejci5b917642015-07-02 09:03:13 +02001702 /* and neither any other deviate statement is expected,
1703 * not-supported deviation must be the only deviation of the target
1704 */
1705 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001706 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1707 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001708 goto error;
1709 }
1710
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001711 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001712 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1713 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1714 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001715 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1716 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001717 goto error;
1718 }
1719 }
1720 }
Radek Krejci5b917642015-07-02 09:03:13 +02001721
Michal Vaskoff006c12016-02-17 11:15:19 +01001722 /* unlink and store the original node */
1723 lys_node_unlink(dev_target);
1724 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001725
Radek Krejci5b917642015-07-02 09:03:13 +02001726 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02001727 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02001728 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 } else if (!strcmp(value, "add")) {
1730 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1731 } else if (!strcmp(value, "replace")) {
1732 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1733 } else if (!strcmp(value, "delete")) {
1734 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1735 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001736 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001737 goto error;
1738 }
1739 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001740 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001741
Michal Vaskoff006c12016-02-17 11:15:19 +01001742 /* store a shallow copy of the original node */
1743 if (!dev->orig_node) {
1744 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001745 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01001746 /* just to be safe */
1747 if (tmp_unres.count) {
1748 LOGINT;
1749 goto error;
1750 }
1751 }
1752
Radek Krejcieb00f512015-07-01 16:44:58 +02001753 /* process deviation properties */
1754 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001755 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1756 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001757 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001758 continue;
1759 }
1760
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001762 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001763 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001764 goto error;
1765 }
1766
1767 /* for we deviate from RFC 6020 and allow config property even it is/is not
1768 * specified in the target explicitly since config property inherits. So we expect
1769 * that config is specified in every node. But for delete, we check that the value
1770 * is the same as here in deviation
1771 */
1772 GETVAL(value, child, "value");
1773 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001774 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001775 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001776 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001777 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001778 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 goto error;
1780 }
1781
1782 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001783 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001784 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001785 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001786 } else { /* add and replace are the same in this case */
1787 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001788 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001789
1790 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001791 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001792 }
1793 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001794 c_dflt++;
1795
1796 /* check target node type */
1797 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1798 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1799 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1800 goto error;
1801 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1802 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1803 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1804 goto error;
1805 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
1806 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1807 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001808 goto error;
1809 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001810
Radek Krejcid5a5c282016-08-15 15:38:08 +02001811 /* skip lyxml_free() at the end of the loop, this node will be processed later */
1812 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02001813
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001815 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001816 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001817 goto error;
1818 }
1819
1820 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001821 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001822 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1823 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 goto error;
1825 }
1826
1827 GETVAL(value, child, "value");
1828 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001829 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001830 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001831 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001832 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001833 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001834 goto error;
1835 }
1836
1837 if (d->mod == LY_DEVIATE_ADD) {
1838 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001839 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001840 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1841 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001842 goto error;
1843 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001844
Radek Krejci841ec082016-04-05 13:05:17 +02001845 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02001846 if (d->flags & LYS_MAND_TRUE) {
1847 if (dev_target->nodetype == LYS_CHOICE) {
1848 if (((struct lys_node_choice *)(dev_target))->dflt) {
1849 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1850 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1851 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
1852 goto error;
1853 }
1854 } else if (dev_target->nodetype == LYS_LEAF) {
1855 if (((struct lys_node_leaf *)(dev_target))->dflt) {
1856 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1857 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1858 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
1859 goto error;
1860 }
1861 }
Radek Krejci841ec082016-04-05 13:05:17 +02001862 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001863
Michal Vasko21be1b32016-03-07 12:31:34 +01001864 dev_target->flags |= d->flags & LYS_MAND_MASK;
1865 } else if (d->mod == LY_DEVIATE_RPL) {
1866 /* check that there was a value before */
1867 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001868 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1869 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001870 goto error;
1871 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001872
Michal Vasko21be1b32016-03-07 12:31:34 +01001873 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001874 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001875 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001876 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001877 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001878 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001879 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001880
1881 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
1882 for (parent = dev_target->parent;
1883 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1884 parent = parent->parent) {
1885 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1886 /* stop also on presence containers */
1887 break;
1888 }
1889 }
1890 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1891 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1892 if (lyp_check_mandatory_choice(parent)) {
1893 goto error;
1894 }
1895 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001896 } else if (!strcmp(child->name, "min-elements")) {
1897 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001898 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001899 goto error;
1900 }
1901 f_min = 1;
1902
Michal Vasko60f4b452016-02-12 11:02:55 +01001903 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001904 goto error;
1905 }
1906 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001907 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001908 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001909 goto error;
1910 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001911 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001912
Michal Vasko60f4b452016-02-12 11:02:55 +01001913 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001914 goto error;
1915 }
1916 } else if (!strcmp(child->name, "must")) {
1917 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001918 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001919 continue;
1920 } else if (!strcmp(child->name, "type")) {
1921 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001922 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 goto error;
1924 }
1925
Michal Vaskof7e57d52016-03-07 11:31:09 +01001926 /* add, del type is forbidden */
1927 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001928 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001929 goto error;
1930 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001931 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001932 goto error;
1933 }
1934
Radek Krejcieb00f512015-07-01 16:44:58 +02001935 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001936 if (dev_target->nodetype == LYS_LEAF) {
1937 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001938 if (((struct lys_node_leaf *)dev_target)->dflt) {
1939 ly_set_add(dflt_check, dev_target, 0);
1940 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001941 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1942 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001943 if (((struct lys_node_leaflist *)dev_target)->dflt) {
1944 ly_set_add(dflt_check, dev_target, 0);
1945 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001946 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001947 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1948 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001949 goto error;
1950 }
1951
Radek Krejcieb00f512015-07-01 16:44:58 +02001952 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001953 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001954 /* HACK for unres */
1955 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001956 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 goto error;
1958 }
1959 d->type = t;
1960 } else if (!strcmp(child->name, "unique")) {
1961 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001962 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001963 continue;
1964 } else if (!strcmp(child->name, "units")) {
1965 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001966 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001967 goto error;
1968 }
1969
1970 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001971 if (dev_target->nodetype == LYS_LEAFLIST) {
1972 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1973 } else if (dev_target->nodetype == LYS_LEAF) {
1974 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001975 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001976 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1977 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001978 goto error;
1979 }
1980
1981 /* get units value */
1982 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001983 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001984
1985 /* apply to target */
1986 if (d->mod == LY_DEVIATE_ADD) {
1987 /* check that there is no current value */
1988 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001989 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1990 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001991 goto error;
1992 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001993
Michal Vasko21be1b32016-03-07 12:31:34 +01001994 *stritem = lydict_insert(ctx, value, 0);
1995 } else if (d->mod == LY_DEVIATE_RPL) {
1996 /* check that there was a value before */
1997 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001998 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1999 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002000 goto error;
2001 }
2002
2003 lydict_remove(ctx, *stritem);
2004 *stritem = lydict_insert(ctx, value, 0);
2005 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002006 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002007 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002008 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2009 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002010 goto error;
2011 }
2012 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002013 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002014 }
2015 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002016 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002017 goto error;
2018 }
2019
Michal Vasko88c29542015-11-27 14:57:53 +01002020 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002021 }
2022
2023 if (c_must) {
2024 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002025 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002026 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002027 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2028 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002029 break;
Radek Krejci76512572015-08-04 09:47:08 +02002030 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002031 trg_must = &((struct lys_node_container *)dev_target)->must;
2032 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002033 break;
Radek Krejci76512572015-08-04 09:47:08 +02002034 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002035 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2036 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002037 break;
Radek Krejci76512572015-08-04 09:47:08 +02002038 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002039 trg_must = &((struct lys_node_list *)dev_target)->must;
2040 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002041 break;
Radek Krejci76512572015-08-04 09:47:08 +02002042 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002043 case LYS_ANYDATA:
2044 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2045 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002046 break;
2047 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002048 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2049 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002050 goto error;
2051 }
2052
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002053 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002054
Radek Krejcieb00f512015-07-01 16:44:58 +02002055 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002056 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002057 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002058 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002059 } else if (d->mod == LY_DEVIATE_ADD) {
2060 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002061 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002062 if (!d->must) {
2063 LOGMEM;
2064 goto error;
2065 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002066 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002067 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002068 d->must_size = c_must;
2069 } else { /* LY_DEVIATE_DEL */
2070 d->must = calloc(c_must, sizeof *d->must);
2071 }
Michal Vasko253035f2015-12-17 16:58:13 +01002072 if (!d->must) {
2073 LOGMEM;
2074 goto error;
2075 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002076 }
2077 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002078 /* replace unique is forbidden */
2079 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002080 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002081 goto error;
2082 }
2083
Radek Krejcieb00f512015-07-01 16:44:58 +02002084 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002085 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002086 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2087 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 goto error;
2089 }
2090
Michal Vasko60f4b452016-02-12 11:02:55 +01002091 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002092 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002093 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002094 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002095 list->unique = d->unique;
2096 d->unique = &list->unique[list->unique_size];
2097 d->unique_size = c_uniq;
2098 } else { /* LY_DEVIATE_DEL */
2099 d->unique = calloc(c_uniq, sizeof *d->unique);
2100 }
Michal Vasko253035f2015-12-17 16:58:13 +01002101 if (!d->unique) {
2102 LOGMEM;
2103 goto error;
2104 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002105 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002106 if (c_dflt) {
2107 if (d->mod == LY_DEVIATE_ADD) {
2108 /* check that there is no current value */
2109 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2110 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2111 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2112 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2113 goto error;
2114 }
2115
2116 /* check collision with mandatory/min-elements */
2117 if ((dev_target->flags & LYS_MAND_TRUE) ||
2118 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2119 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2120 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2121 "Adding the \"default\" statement is forbidden on %s statement.",
2122 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2123 goto error;
2124 }
2125 } else if (d->mod == LY_DEVIATE_RPL) {
2126 /* check that there was a value before */
2127 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2128 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2129 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2131 goto error;
2132 }
2133 }
2134
2135 if (dev_target->nodetype == LYS_LEAFLIST) {
2136 /* reallocate default list in the target */
2137 llist = (struct lys_node_leaflist *)dev_target;
2138 if (d->mod == LY_DEVIATE_ADD) {
2139 /* reallocate (enlarge) the unique array of the target */
2140 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2141 } else if (d->mod == LY_DEVIATE_RPL) {
2142 /* reallocate (replace) the unique array of the target */
2143 for (i = 0; i < llist->dflt_size; i++) {
2144 lydict_remove(llist->module->ctx, llist->dflt[i]);
2145 }
2146 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2147 llist->dflt_size = 0;
2148 }
2149 }
2150 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2151 if (!d->dflt) {
2152 LOGMEM;
2153 goto error;
2154 }
2155 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002156
2157 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002158 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002159 if (!strcmp(child->name, "must")) {
2160 if (d->mod == LY_DEVIATE_DEL) {
2161 if (fill_yin_must(module, child, &d->must[d->must_size])) {
2162 goto error;
2163 }
2164
2165 /* find must to delete, we are ok with just matching conditions */
2166 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002167 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002168 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002169 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002170 /* ... and maintain the array */
2171 (*trg_must_size)--;
2172 if (i != *trg_must_size) {
2173 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2174 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2175 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2176 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2177 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2178 }
2179 if (!(*trg_must_size)) {
2180 free(*trg_must);
2181 *trg_must = NULL;
2182 } else {
2183 (*trg_must)[*trg_must_size].expr = NULL;
2184 (*trg_must)[*trg_must_size].dsc = NULL;
2185 (*trg_must)[*trg_must_size].ref = NULL;
2186 (*trg_must)[*trg_must_size].eapptag = NULL;
2187 (*trg_must)[*trg_must_size].emsg = NULL;
2188 }
2189
2190 i = -1; /* set match flag */
2191 break;
2192 }
2193 }
2194 d->must_size++;
2195 if (i != -1) {
2196 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002197 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002198 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002199 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002200 goto error;
2201 }
2202 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002203 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2204 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002205 goto error;
2206 }
2207 (*trg_must_size)++;
2208 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002209
2210 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002211 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002212 goto error;
2213 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002214 } else if (!strcmp(child->name, "unique")) {
2215 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002216 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002217 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002218 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002219 goto error;
2220 }
2221
2222 /* find unique structures to delete */
2223 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002224 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002225 continue;
2226 }
2227
Radek Krejci581ce772015-11-10 17:22:40 +01002228 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002229 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 break;
2231 }
2232 }
2233
Radek Krejci581ce772015-11-10 17:22:40 +01002234 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002236 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002237 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002238 }
2239 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002240 /* ... and maintain the array */
2241 list->unique_size--;
2242 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002243 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2244 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002245 }
2246
2247 if (!list->unique_size) {
2248 free(list->unique);
2249 list->unique = NULL;
2250 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002251 list->unique[list->unique_size].expr_size = 0;
2252 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002253 }
2254
2255 i = -1; /* set match flag */
2256 break;
2257 }
2258 }
2259
2260 d->unique_size++;
2261 if (i != -1) {
2262 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002263 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2264 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002265 goto error;
2266 }
2267 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002268 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002269 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002270 list->unique_size++;
2271 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002272 goto error;
2273 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002274 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002275 } else if (!strcmp(child->name, "default")) {
2276 GETVAL(value, child, "value");
2277 u = strlen(value);
2278 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2279
2280 if (dev_target->nodetype == LYS_CHOICE) {
2281 choice = (struct lys_node_choice *)dev_target;
2282 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2283 if (rc || !node) {
2284 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2285 goto error;
2286 }
2287 if (d->mod == LY_DEVIATE_DEL) {
2288 if (!choice->dflt || (choice->dflt != node)) {
2289 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2290 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2291 goto error;
2292 }
2293 } else { /* add or replace */
2294 choice->dflt = node;
2295 if (!choice->dflt) {
2296 /* default branch not found */
2297 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2298 goto error;
2299 }
2300 }
2301 } else if (dev_target->nodetype == LYS_LEAF) {
2302 leaf = (struct lys_node_leaf *)dev_target;
2303 if (d->mod == LY_DEVIATE_DEL) {
2304 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2305 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2306 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2307 goto error;
2308 }
2309 /* remove value */
2310 lydict_remove(ctx, leaf->dflt);
2311 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002312 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002313 } else { /* add (already checked) and replace */
2314 /* remove value */
2315 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002316 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002317
2318 /* set new value */
2319 leaf->dflt = lydict_insert(ctx, value, u);
2320
Radek Krejcibd117f02016-11-04 16:28:08 +01002321 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002322 ly_set_add(dflt_check, dev_target, 0);
2323 }
2324 } else { /* LYS_LEAFLIST */
2325 llist = (struct lys_node_leaflist *)dev_target;
2326 if (d->mod == LY_DEVIATE_DEL) {
2327 /* find and remove the value in target list */
2328 for (i = 0; i < llist->dflt_size; i++) {
2329 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2330 /* match, remove the value */
2331 lydict_remove(llist->module->ctx, llist->dflt[i]);
2332 llist->dflt[i] = NULL;
2333 break;
2334 }
2335 }
2336 if (i == llist->dflt_size) {
2337 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2338 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2339 goto error;
2340 }
2341 } else {
2342 /* add or replace, anyway we place items into the deviate's list
2343 which propagates to the target */
2344 /* we just want to check that the value isn't already in the list */
2345 for (i = 0; i < llist->dflt_size; i++) {
2346 if (ly_strequal(llist->dflt[i], value, 1)) {
2347 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2348 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2349 goto error;
2350 }
2351 }
2352 /* store it in target node */
2353 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2354
2355 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2356 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01002357 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002358 }
2359 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002361 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002362
2363 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2364 /* consolidate the final list in the target after removing items from it */
2365 llist = (struct lys_node_leaflist *)dev_target;
2366 for (i = j = 0; j < llist->dflt_size; j++) {
2367 llist->dflt[i] = llist->dflt[j];
2368 if (llist->dflt[i]) {
2369 i++;
2370 }
2371 }
2372 llist->dflt_size = i + 1;
2373 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002374 }
2375
Michal Vasko43a1feb2016-03-07 12:03:02 +01002376 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002377 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002378 value = NULL;
2379 rc = EXIT_SUCCESS;
2380 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2381 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002382 value = leaf->dflt;
2383 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002384 } else { /* LYS_LEAFLIST */
2385 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2386 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002387 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2388 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002389 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002390 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002391 break;
2392 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002393 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002394
2395 }
2396 if (rc == -1) {
2397 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2398 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2399 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2400 dev->target_name);
2401 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002402 }
2403 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002404
Radek Krejci27fe55e2016-09-13 17:13:35 +02002405 /* mark all the affected modules as deviated and implemented */
2406 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2407 mod = lys_node_module(parent);
2408 if (module != mod) {
2409 mod->deviated = 1;
2410 lys_set_implemented(mod);
2411 }
2412 }
2413
Radek Krejcid5a5c282016-08-15 15:38:08 +02002414 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002415 return EXIT_SUCCESS;
2416
2417error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002418 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002419 return EXIT_FAILURE;
2420}
2421
Michal Vasko0d343d12015-08-24 14:57:36 +02002422/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002423static int
Radek Krejcib8048692015-08-05 13:36:34 +02002424fill_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 +02002425 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002426{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002428 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002429 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002430 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002431
Michal Vasko591e0b22015-08-13 13:53:43 +02002432 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002434 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002435 if (!aug->target_name) {
2436 goto error;
2437 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002439
Michal Vasko1d87a922015-08-21 12:57:16 +02002440 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002441 goto error;
2442 }
2443
2444 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002445 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2446 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002447 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002448 continue;
2449 }
2450
Radek Krejci3cf9e222015-06-18 11:37:50 +02002451 if (!strcmp(child->name, "if-feature")) {
2452 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002453 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002454 } else if (!strcmp(child->name, "when")) {
2455 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002456 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002457 goto error;
2458 }
2459
2460 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002461 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002462 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002463 goto error;
2464 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002465 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002466 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002467
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002468 /* check allowed data sub-statements */
2469 } else if (!strcmp(child->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002470 node = read_yin_container(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002471 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002472 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002473 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002474 node = read_yin_leaf(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002475 } else if (!strcmp(child->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002476 node = read_yin_list(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002477 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002478 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002479 } else if (!strcmp(child->name, "choice")) {
Pavol Vican9c3318f2016-10-24 11:32:48 +02002480 node = read_yin_choice(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002481 } else if (!strcmp(child->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002482 node = read_yin_case(module, (struct lys_node *)aug, child, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002483 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002484 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYXML, 1, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02002485 } else if (!strcmp(child->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002486 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYDATA, 1, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002487 } else if (!strcmp(child->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002488 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02002489 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002490 node = read_yin_notif(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002491 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002492 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002493 goto error;
2494 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002495
Radek Krejci1d82ef62015-08-07 14:44:40 +02002496 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002497 goto error;
2498 }
2499
Radek Krejci1d82ef62015-08-07 14:44:40 +02002500 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002501 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002502 }
2503
2504 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002505 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2506 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002507 LOGMEM;
2508 goto error;
2509 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002510 }
2511
2512 LY_TREE_FOR_SAFE(yin->child, next, child) {
2513 if (!strcmp(child->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02002514 ret = fill_yin_iffeature((struct lys_node *)aug, 0, child, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002515 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002516 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002517 goto error;
2518 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002519 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002520 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002521 }
2522
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002523 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002524 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002525 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002526 * when the uses does and cannot be resolved now for sure
2527 * (the grouping was not yet copied into uses).
2528 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002529 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002530 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002531 goto error;
2532 }
Michal Vasko49291b32015-08-06 09:49:41 +02002533 }
Radek Krejci106efc02015-06-10 14:36:27 +02002534
Michal Vasko508a50d2016-09-07 14:50:33 +02002535 /* check XPath dependencies */
2536 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2537 goto error;
2538 }
2539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002541
2542error:
2543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002544 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002545}
2546
Michal Vasko0d343d12015-08-24 14:57:36 +02002547/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002549fill_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 +02002550{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002551 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 struct lyxml_elem *sub, *next;
2553 const char *value;
2554 char *endptr;
2555 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci200bf712016-08-16 17:11:04 +02002556 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002557 int r;
2558 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002559
Radek Krejci363bd4a2016-07-29 14:30:20 +02002560 assert(uses);
2561 module = uses->module; /* shorthand */
2562
Michal Vaskoe022a562016-09-27 14:24:15 +02002563 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CFG_PARSE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 goto error;
2565 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002566
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002567 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002568 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002569 if (!rfn->target_name) {
2570 goto error;
2571 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002574 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2575 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002576 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002577 continue;
2578 }
2579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 /* limited applicability */
2581 if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002582 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002584 /* check possibility of statements combination */
2585 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002586 if (c_dflt) {
2587 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002588 if (module->version < 2) {
2589 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2590 goto error;
2591 }
Radek Krejci200bf712016-08-16 17:11:04 +02002592 rfn->target_type &= LYS_LEAFLIST;
2593 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002594 if (module->version < 2) {
2595 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2596 } else {
2597 /* YANG 1.1 */
2598 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2599 }
Radek Krejci200bf712016-08-16 17:11:04 +02002600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002601 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002602 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2603 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 goto error;
2605 }
2606 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002607 if (module->version < 2) {
2608 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2609 } else {
2610 /* YANG 1.1 */
2611 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2612 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002613 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002614
Radek Krejci200bf712016-08-16 17:11:04 +02002615 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002616 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 } else if (!strcmp(sub->name, "mandatory")) {
2618 /* leaf, choice or anyxml */
2619 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002620 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002621 goto error;
2622 }
2623 /* just checking the flags in leaf is not sufficient, we would allow
2624 * multiple mandatory statements with the "false" value
2625 */
2626 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 /* check possibility of statements combination */
2629 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002630 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002632 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2633 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 goto error;
2635 }
2636 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002637 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640 GETVAL(value, sub, "value");
2641 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002642 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002644 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002646 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 goto error;
2648 }
2649 } else if (!strcmp(sub->name, "min-elements")) {
2650 /* list or leaf-list */
2651 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002652 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002653 goto error;
2654 }
2655 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002657 /* check possibility of statements combination */
2658 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002659 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002661 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2662 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663 goto error;
2664 }
2665 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002666 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 GETVAL(value, sub, "value");
2670 while (isspace(value[0])) {
2671 value++;
2672 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 /* convert it to uint32_t */
2675 errno = 0;
2676 endptr = NULL;
2677 val = strtoul(value, &endptr, 10);
2678 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002679 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 goto error;
2681 }
2682 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002683 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 } else if (!strcmp(sub->name, "max-elements")) {
2685 /* list or leaf-list */
2686 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002687 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 goto error;
2689 }
2690 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 /* check possibility of statements combination */
2693 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002694 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002696 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2697 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002698 goto error;
2699 }
2700 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002701 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002704 GETVAL(value, sub, "value");
2705 while (isspace(value[0])) {
2706 value++;
2707 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002708
Radek Krejci0d7b2472016-02-12 11:11:03 +01002709 if (!strcmp(value, "unbounded")) {
2710 rfn->mod.list.max = 0;
2711 } else {
2712 /* convert it to uint32_t */
2713 errno = 0;
2714 endptr = NULL;
2715 val = strtoul(value, &endptr, 10);
2716 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002717 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002718 goto error;
2719 }
2720 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002722 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 } else if (!strcmp(sub->name, "presence")) {
2724 /* container */
2725 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002726 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 goto error;
2728 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 /* check possibility of statements combination */
2731 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002732 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002734 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2735 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 goto error;
2737 }
2738 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002739 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002742 GETVAL(value, sub, "value");
2743 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2744 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002745 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 /* check possibility of statements combination */
2747 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002748 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002750 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2751 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002752 goto error;
2753 }
2754 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002755 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002756 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002759 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002760
Radek Krejci363bd4a2016-07-29 14:30:20 +02002761 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2762 /* leaf, leaf-list, list, container or anyxml */
2763 /* check possibility of statements combination */
2764 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002765 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002766 if (!rfn->target_type) {
2767 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2768 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2769 goto error;
2770 }
2771 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002772 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002773 }
2774
2775 c_ftrs++;
2776 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002777 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002778 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 goto error;
2780 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002781
Michal Vasko345da0a2015-12-02 10:35:55 +01002782 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 /* process nodes with cardinality of 0..n */
2786 if (c_must) {
2787 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002788 if (!rfn->must) {
2789 LOGMEM;
2790 goto error;
2791 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002793 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002794 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002795 if (!rfn->iffeature) {
2796 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002797 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002798 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 }
Radek Krejci200bf712016-08-16 17:11:04 +02002800 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002801 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002802 if (!rfn->dflt) {
2803 LOGMEM;
2804 goto error;
2805 }
2806 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002807
Radek Krejci363bd4a2016-07-29 14:30:20 +02002808 LY_TREE_FOR(yin->child, sub) {
2809 if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02002810 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002811 rfn->iffeature_size++;
2812 if (r) {
2813 goto error;
2814 }
Radek Krejci200bf712016-08-16 17:11:04 +02002815 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002816 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2817 rfn->must_size++;
2818 if (r) {
2819 goto error;
2820 }
Radek Krejci200bf712016-08-16 17:11:04 +02002821 } else { /* default */
2822 GETVAL(value, sub, "value");
2823
2824 /* check for duplicity */
2825 for (r = 0; r < rfn->dflt_size; r++) {
2826 if (ly_strequal(rfn->dflt[r], value, 1)) {
2827 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2828 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2829 goto error;
2830 }
2831 }
2832 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02002833 }
2834 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002837
2838error:
2839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002841}
2842
Michal Vasko0d343d12015-08-24 14:57:36 +02002843/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844static int
Radek Krejcib8048692015-08-05 13:36:34 +02002845fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002846{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002847 struct lyxml_elem *child;
2848 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002851 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2852 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002853 continue;
2854 }
2855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 if (!strcmp(child->name, "prefix")) {
2857 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002858 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002859 goto error;
2860 }
2861 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2862 } else if (!strcmp(child->name, "revision-date")) {
2863 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002864 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2865 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 }
2867 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002868 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 goto error;
2870 }
2871 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002872 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002873 if (imp->dsc) {
2874 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2875 goto error;
2876 }
2877 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2878 if (!imp->dsc) {
2879 goto error;
2880 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002881 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002882 if (imp->ref) {
2883 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2884 goto error;
2885 }
2886 imp->ref = read_yin_subnode(module->ctx, child, "text");
2887 if (!imp->ref) {
2888 goto error;
2889 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002891 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 goto error;
2893 }
2894 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002896 /* check mandatory information */
2897 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002898 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 goto error;
2900 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002903
Pavol Vicane994fda2016-03-22 10:47:58 +01002904 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002905
2906error:
2907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002909}
2910
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002911/* logs directly
2912 * returns:
2913 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01002914 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002915 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002916static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002917fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2918 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002919{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 struct lyxml_elem *child;
2921 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002924 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2925 /* garbage */
2926 continue;
2927 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002928 if (!strcmp(child->name, "revision-date")) {
2929 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002930 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931 goto error;
2932 }
2933 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002934 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935 goto error;
2936 }
2937 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002938 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002939 if (inc->dsc) {
2940 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2941 goto error;
2942 }
2943 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2944 if (!inc->dsc) {
2945 goto error;
2946 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002947 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002948 if (inc->ref) {
2949 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2950 goto error;
2951 }
2952 inc->ref = read_yin_subnode(module->ctx, child, "text");
2953 if (!inc->ref) {
2954 goto error;
2955 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002957 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 goto error;
2959 }
2960 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002962 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002963
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01002964 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002965
2966error:
2967
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002968 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002969}
2970
Michal Vasko0d343d12015-08-24 14:57:36 +02002971/* logs directly
2972 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002973 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002974 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002975 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002976 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977static int
Radek Krejcib8048692015-08-05 13:36:34 +02002978read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002979 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002980{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 const char *value;
2982 struct lyxml_elem *sub, *next;
2983 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002986 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002989 if (opt & OPT_IDENT) {
2990 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002991 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 goto error;
2993 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002994 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002995 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002996
Radek Krejci6764bb32015-07-03 15:16:04 +02002997 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002998 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002999 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02003000 }
3001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 /* process local parameters */
3003 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003004 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003005 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003006 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003007 continue;
3008 }
3009 if (strcmp(sub->ns->value, LY_NSYIN)) {
3010 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02003011 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003012 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003013 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02003014 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003015 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02003016 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003017 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02003018 goto error;
3019 }
3020 }
3021
3022 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003023 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003024 continue;
3025 }
3026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003028 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003029 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 goto error;
3031 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003032 node->dsc = read_yin_subnode(ctx, sub, "text");
3033 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003034 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 }
3036 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003037 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003038 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 goto error;
3040 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003041 node->ref = read_yin_subnode(ctx, sub, "text");
3042 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003043 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 }
3045 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003046 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003047 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 goto error;
3049 }
3050 GETVAL(value, sub, "value");
3051 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003052 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003054 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003056 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003058 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003059 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003061 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3062 if (opt & OPT_CFG_PARSE) {
3063 if (node->flags & LYS_CONFIG_MASK) {
3064 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3065 goto error;
3066 }
3067 GETVAL(value, sub, "value");
3068 if (!strcmp(value, "false")) {
3069 node->flags |= LYS_CONFIG_R;
3070 } else if (!strcmp(value, "true")) {
3071 node->flags |= LYS_CONFIG_W;
3072 } else {
3073 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3074 goto error;
3075 }
3076 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003079 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 continue;
3081 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003082 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003084
Michal Vaskoe022a562016-09-27 14:24:15 +02003085 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003087 if (parent) {
3088 node->flags |= parent->flags & LYS_CONFIG_MASK;
3089 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003091 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 }
3093 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003096
3097error:
3098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003100}
3101
Michal Vasko0d343d12015-08-24 14:57:36 +02003102/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003103static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003104read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003105{
Radek Krejci76512572015-08-04 09:47:08 +02003106 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003107 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003108 const char *value;
3109
3110 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003111 if (!retval) {
3112 LOGMEM;
3113 return NULL;
3114 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003115
3116 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003117 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003118 if (!retval->cond) {
3119 goto error;
3120 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003121
Radek Krejci73adb602015-07-02 18:07:40 +02003122 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003123 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3124 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003125 continue;
3126 }
3127
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003128 if (!strcmp(child->name, "description")) {
3129 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003130 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003131 goto error;
3132 }
3133 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3134 if (!retval->dsc) {
3135 goto error;
3136 }
3137 } else if (!strcmp(child->name, "reference")) {
3138 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003139 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003140 goto error;
3141 }
3142 retval->ref = read_yin_subnode(module->ctx, child, "text");
3143 if (!retval->ref) {
3144 goto error;
3145 }
3146 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003147 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003148 goto error;
3149 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003150 }
3151
3152 return retval;
3153
3154error:
3155
Michal Vasko0308dd62015-10-07 09:14:40 +02003156 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003157 return NULL;
3158}
3159
Michal Vasko0d343d12015-08-24 14:57:36 +02003160/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003161static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003162read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003163 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003164{
Michal Vasko29fc0182015-08-24 15:02:39 +02003165 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003166 struct lys_node_case *cs;
3167 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02003168 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003169
Radek Krejcie867c852015-08-27 09:52:34 +02003170 /* init */
3171 memset(&root, 0, sizeof root);
3172
Radek Krejci1d82ef62015-08-07 14:44:40 +02003173 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003174 if (!cs) {
3175 LOGMEM;
3176 return NULL;
3177 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003178 cs->nodetype = LYS_CASE;
3179 cs->prev = (struct lys_node *)cs;
3180 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003181
Michal Vaskoe022a562016-09-27 14:24:15 +02003182 if (read_yin_common(module, parent, retval, yin,
3183 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0) | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003184 goto error;
3185 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003186
Radek Krejcia9544502015-08-14 08:24:29 +02003187 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3188
Michal Vasko3a0043f2015-08-12 12:11:30 +02003189 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003190 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003191 goto error;
3192 }
3193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 /* process choice's specific children */
3195 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003196 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3197 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003198 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003199 continue;
3200 }
3201
Michal Vasko29fc0182015-08-24 15:02:39 +02003202 if (!strcmp(sub->name, "container") ||
3203 !strcmp(sub->name, "leaf-list") ||
3204 !strcmp(sub->name, "leaf") ||
3205 !strcmp(sub->name, "list") ||
3206 !strcmp(sub->name, "uses") ||
3207 !strcmp(sub->name, "choice") ||
3208 !strcmp(sub->name, "anyxml")) {
3209
Michal Vaskof3930de2015-10-22 12:03:59 +02003210 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003211 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003212 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003213 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01003214 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02003215 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003216 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003217 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003218 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003219 goto error;
3220 }
3221
Radek Krejci1d82ef62015-08-07 14:44:40 +02003222 cs->when = read_yin_when(module, sub);
3223 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003224 goto error;
3225 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003226
Michal Vasko345da0a2015-12-02 10:35:55 +01003227 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003229 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003233
Radek Krejci3cf9e222015-06-18 11:37:50 +02003234 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003235 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3236 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003237 LOGMEM;
3238 goto error;
3239 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003240 }
Radek Krejci73adb602015-07-02 18:07:40 +02003241 LY_TREE_FOR(yin->child, sub) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003242 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003243 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003244 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003245 goto error;
3246 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 }
Radek Krejcib388c152015-06-04 17:03:03 +02003248
Michal Vasko29fc0182015-08-24 15:02:39 +02003249 /* last part - process data nodes */
3250 LY_TREE_FOR_SAFE(root.child, next, sub) {
3251 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003252 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003253 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003254 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003255 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003256 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003257 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003258 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003259 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003260 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003261 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003262 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003263 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003264 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003265 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003266 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003267 }
3268 if (!node) {
3269 goto error;
3270 }
3271
Michal Vasko345da0a2015-12-02 10:35:55 +01003272 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003273 }
3274
Michal Vasko508a50d2016-09-07 14:50:33 +02003275 /* check XPath dependencies */
3276 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3277 goto error;
3278 }
3279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003281
3282error:
3283
Michal Vasko29fc0182015-08-24 15:02:39 +02003284 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003285 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003286 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003287 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003290}
3291
Michal Vasko0d343d12015-08-24 14:57:36 +02003292/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003293static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003294read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3295 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003296{
Radek Krejci629cdef2016-06-06 15:06:36 +02003297 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003299 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003300 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003301 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02003302 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003305 if (!choice) {
3306 LOGMEM;
3307 return NULL;
3308 }
Radek Krejci76512572015-08-04 09:47:08 +02003309 choice->nodetype = LYS_CHOICE;
3310 choice->prev = (struct lys_node *)choice;
3311 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003312
Michal Vaskoe022a562016-09-27 14:24:15 +02003313 if (read_yin_common(module, parent, retval, yin,
3314 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3315 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 goto error;
3317 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003318
Radek Krejcia9544502015-08-14 08:24:29 +02003319 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3320
Michal Vasko3a0043f2015-08-12 12:11:30 +02003321 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003322 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003323 goto error;
3324 }
3325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 /* process choice's specific children */
3327 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003328 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3329 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003330 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003331 continue;
3332 }
3333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003335 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 goto error;
3337 }
3338 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003339 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 goto error;
3341 }
3342 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003343 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 goto error;
3345 }
3346 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003347 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 goto error;
3349 }
3350 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003351 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
3354 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003355 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003356 goto error;
3357 }
3358 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003359 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 goto error;
3361 }
3362 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003363 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003364 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 goto error;
3366 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003367 dflt = sub;
3368 lyxml_unlink_elem(ctx, dflt, 0);
3369
Radek Krejcif9a312c2016-06-06 15:14:30 +02003370 continue;
3371 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 } else if (!strcmp(sub->name, "mandatory")) {
3374 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003375 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 goto error;
3377 }
3378 /* just checking the flags in leaf is not sufficient, we would allow
3379 * multiple mandatory statements with the "false" value
3380 */
3381 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 GETVAL(value, sub, "value");
3384 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003385 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003386 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003387 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003388 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003389 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 goto error;
3391 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003392 } else if (!strcmp(sub->name, "when")) {
3393 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003394 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003395 goto error;
3396 }
3397
3398 choice->when = read_yin_when(module, sub);
3399 if (!choice->when) {
3400 goto error;
3401 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003402 } else if (!strcmp(sub->name, "if-feature")) {
3403 c_ftrs++;
3404
Michal Vasko345da0a2015-12-02 10:35:55 +01003405 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003406 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003407 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003408 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02003409 goto error;
3410 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003412 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003413 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003415
Radek Krejci1d82ef62015-08-07 14:44:40 +02003416 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003417 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003419
Radek Krejci3cf9e222015-06-18 11:37:50 +02003420 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003421 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3422 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003423 LOGMEM;
3424 goto error;
3425 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003426 }
3427
Radek Krejci73adb602015-07-02 18:07:40 +02003428 LY_TREE_FOR(yin->child, sub) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003429 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003430 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003431 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003432 goto error;
3433 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003434 }
3435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003437 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003438 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01003439 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 goto error;
3441 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003444 if (dflt) {
3445 GETVAL(value, dflt, "value");
3446 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003447 goto error;
3448 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003449 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003451
Michal Vasko508a50d2016-09-07 14:50:33 +02003452 /* check XPath dependencies */
3453 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3454 goto error;
3455 }
3456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003458
3459error:
3460
Radek Krejci629cdef2016-06-06 15:06:36 +02003461 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003462 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003465}
3466
Michal Vasko0d343d12015-08-24 14:57:36 +02003467/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003468static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003469read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
3470 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003471{
Radek Krejci76512572015-08-04 09:47:08 +02003472 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003473 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 struct lyxml_elem *sub, *next;
3475 const char *value;
3476 int r;
3477 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003478 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003481 if (!anyxml) {
3482 LOGMEM;
3483 return NULL;
3484 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003485 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003486 anyxml->prev = (struct lys_node *)anyxml;
3487 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003488
Michal Vaskoe022a562016-09-27 14:24:15 +02003489 if (read_yin_common(module, parent, retval, yin,
3490 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3491 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 goto error;
3493 }
Radek Krejci863c2852015-06-03 15:47:11 +02003494
Radek Krejcia9544502015-08-14 08:24:29 +02003495 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003496
Radek Krejcic189a952016-07-11 15:27:07 +02003497 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003498 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003499 goto error;
3500 }
3501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003503 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3504 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003505 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003506 continue;
3507 }
3508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 if (!strcmp(sub->name, "mandatory")) {
3510 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003511 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 goto error;
3513 }
3514 /* just checking the flags in leaf is not sufficient, we would allow
3515 * multiple mandatory statements with the "false" value
3516 */
3517 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003519 GETVAL(value, sub, "value");
3520 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003521 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003522 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003523 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003524 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003525 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003526 goto error;
3527 }
3528 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003529 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003530 } else if (!strcmp(sub->name, "when")) {
3531 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003532 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003533 goto error;
3534 }
3535
3536 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003537 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003538 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003539 goto error;
3540 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003541 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 } else if (!strcmp(sub->name, "must")) {
3543 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003544 } else if (!strcmp(sub->name, "if-feature")) {
3545 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003548 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 }
3551 }
Radek Krejci863c2852015-06-03 15:47:11 +02003552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 /* middle part - process nodes with cardinality of 0..n */
3554 if (c_must) {
3555 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003556 if (!anyxml->must) {
3557 LOGMEM;
3558 goto error;
3559 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003561 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003562 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3563 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003564 LOGMEM;
3565 goto error;
3566 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003567 }
Radek Krejci863c2852015-06-03 15:47:11 +02003568
Radek Krejci73adb602015-07-02 18:07:40 +02003569 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003571 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3572 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 if (r) {
3574 goto error;
3575 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003576 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003577 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003578 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003579 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003580 goto error;
3581 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003583 }
Radek Krejci863c2852015-06-03 15:47:11 +02003584
Michal Vasko508a50d2016-09-07 14:50:33 +02003585 /* check XPath dependencies */
3586 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3587 goto error;
3588 }
3589
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003591
3592error:
3593
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003594 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003597}
3598
Michal Vasko0d343d12015-08-24 14:57:36 +02003599/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003600static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003601read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003602 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003603{
Radek Krejci76512572015-08-04 09:47:08 +02003604 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003605 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 struct lyxml_elem *sub, *next;
3607 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003608 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003609 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003611 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003612 if (!leaf) {
3613 LOGMEM;
3614 return NULL;
3615 }
Radek Krejci76512572015-08-04 09:47:08 +02003616 leaf->nodetype = LYS_LEAF;
3617 leaf->prev = (struct lys_node *)leaf;
3618 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003619
Michal Vaskoe022a562016-09-27 14:24:15 +02003620 if (read_yin_common(module, parent, retval, yin,
3621 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3622 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 goto error;
3624 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003625
Radek Krejcia9544502015-08-14 08:24:29 +02003626 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003627
Radek Krejcic189a952016-07-11 15:27:07 +02003628 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003629 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003630 goto error;
3631 }
3632
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003634 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3635 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003636 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003637 continue;
3638 }
3639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003641 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003642 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 goto error;
3644 }
Michal Vasko88c29542015-11-27 14:57:53 +01003645 /* HACK for unres */
3646 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003647 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003648 /* postpone type resolution when if-feature parsing is done since we need
3649 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003650 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 } else if (!strcmp(sub->name, "default")) {
3652 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003653 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 goto error;
3655 }
3656 GETVAL(value, sub, "value");
3657 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3658 } else if (!strcmp(sub->name, "units")) {
3659 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003660 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003661 goto error;
3662 }
3663 GETVAL(value, sub, "name");
3664 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3665 } else if (!strcmp(sub->name, "mandatory")) {
3666 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003667 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 goto error;
3669 }
3670 /* just checking the flags in leaf is not sufficient, we would allow
3671 * multiple mandatory statements with the "false" value
3672 */
3673 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 GETVAL(value, sub, "value");
3676 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003677 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003678 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003679 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003680 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003681 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 goto error;
3683 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003684 } else if (!strcmp(sub->name, "when")) {
3685 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003686 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003687 goto error;
3688 }
3689
3690 leaf->when = read_yin_when(module, sub);
3691 if (!leaf->when) {
3692 goto error;
3693 }
3694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003696 c_must++;
3697 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003698 } else if (!strcmp(sub->name, "if-feature")) {
3699 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003703 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003706
Michal Vasko88c29542015-11-27 14:57:53 +01003707 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003711 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003712 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 goto error;
3714 }
Michal Vasko478c4652016-07-21 12:55:01 +02003715 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003716 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01003717 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02003718 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3719 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 /* middle part - process nodes with cardinality of 0..n */
3723 if (c_must) {
3724 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003725 if (!leaf->must) {
3726 LOGMEM;
3727 goto error;
3728 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003730 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003731 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3732 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003733 LOGMEM;
3734 goto error;
3735 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003736 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003737
Radek Krejci73adb602015-07-02 18:07:40 +02003738 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003740 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3741 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 if (r) {
3743 goto error;
3744 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003745 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003746 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003747 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003748 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003749 goto error;
3750 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003753
Radek Krejcicbb473e2016-09-16 14:48:32 +02003754 /* finalize type parsing */
3755 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
3756 leaf->type.der = NULL;
3757 goto error;
3758 }
3759
3760 /* check default value (if not defined, there still could be some restrictions
3761 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01003762 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 +02003763 goto error;
3764 }
3765
Michal Vasko508a50d2016-09-07 14:50:33 +02003766 /* check XPath dependencies */
3767 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3768 goto error;
3769 }
3770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003772
3773error:
3774
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003775 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003778}
3779
Michal Vasko0d343d12015-08-24 14:57:36 +02003780/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003781static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003782read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003783 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003784{
Radek Krejci76512572015-08-04 09:47:08 +02003785 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003786 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 struct lyxml_elem *sub, *next;
3788 const char *value;
3789 char *endptr;
3790 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003791 int r, has_type = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003792 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003796 if (!llist) {
3797 LOGMEM;
3798 return NULL;
3799 }
Radek Krejci76512572015-08-04 09:47:08 +02003800 llist->nodetype = LYS_LEAFLIST;
3801 llist->prev = (struct lys_node *)llist;
3802 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003803
Michal Vaskoe022a562016-09-27 14:24:15 +02003804 if (read_yin_common(module, parent, retval, yin,
3805 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
3806 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 goto error;
3808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003809
Radek Krejcia9544502015-08-14 08:24:29 +02003810 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003811
Radek Krejcic189a952016-07-11 15:27:07 +02003812 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003813 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003814 goto error;
3815 }
3816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003818 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3819 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003820 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003821 continue;
3822 }
3823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003825 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003826 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 goto error;
3828 }
Michal Vasko88c29542015-11-27 14:57:53 +01003829 /* HACK for unres */
3830 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003831 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003832 /* postpone type resolution when if-feature parsing is done since we need
3833 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003834 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 } else if (!strcmp(sub->name, "units")) {
3836 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003837 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 goto error;
3839 }
3840 GETVAL(value, sub, "name");
3841 llist->units = lydict_insert(module->ctx, value, strlen(value));
3842 } else if (!strcmp(sub->name, "ordered-by")) {
3843 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003844 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 goto error;
3846 }
3847 /* just checking the flags in llist is not sufficient, we would
3848 * allow multiple ordered-by statements with the "system" value
3849 */
3850 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003851
Radek Krejci1574a8d2015-08-03 14:16:52 +02003852 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3854 * state data
3855 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003856 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 continue;
3858 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003860 GETVAL(value, sub, "value");
3861 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003862 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003864 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003866 } /* else system is the default value, so we can ignore it */
3867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 } else if (!strcmp(sub->name, "must")) {
3869 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003870 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003871 } else if (!strcmp(sub->name, "if-feature")) {
3872 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003874 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
3875 c_dflt++;
3876 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 } else if (!strcmp(sub->name, "min-elements")) {
3879 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003880 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003881 goto error;
3882 }
3883 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003885 GETVAL(value, sub, "value");
3886 while (isspace(value[0])) {
3887 value++;
3888 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003890 /* convert it to uint32_t */
3891 errno = 0;
3892 endptr = NULL;
3893 val = strtoul(value, &endptr, 10);
3894 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003895 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 goto error;
3897 }
3898 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003899 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003900 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01003901 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003902 goto error;
3903 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 } else if (!strcmp(sub->name, "max-elements")) {
3905 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003906 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 goto error;
3908 }
3909 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 GETVAL(value, sub, "value");
3912 while (isspace(value[0])) {
3913 value++;
3914 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003915
Radek Krejci0d7b2472016-02-12 11:11:03 +01003916 if (!strcmp(value, "unbounded")) {
3917 llist->max = 0;
3918 } else {
3919 /* convert it to uint32_t */
3920 errno = 0;
3921 endptr = NULL;
3922 val = strtoul(value, &endptr, 10);
3923 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003924 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003925 goto error;
3926 }
3927 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003928 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003929 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01003930 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003931 goto error;
3932 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003933 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003934 } else if (!strcmp(sub->name, "when")) {
3935 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003936 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003937 goto error;
3938 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003939
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003940 llist->when = read_yin_when(module, sub);
3941 if (!llist->when) {
3942 goto error;
3943 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003944 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003945 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003948
Michal Vasko88c29542015-11-27 14:57:53 +01003949 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003950 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003953 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003954 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 goto error;
3956 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 /* middle part - process nodes with cardinality of 0..n */
3959 if (c_must) {
3960 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003961 if (!llist->must) {
3962 LOGMEM;
3963 goto error;
3964 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003966 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003967 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3968 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003969 LOGMEM;
3970 goto error;
3971 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003972 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003973 if (c_dflt) {
3974 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
3975 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003976 LOGMEM;
3977 goto error;
3978 }
3979 }
3980
Radek Krejci73adb602015-07-02 18:07:40 +02003981 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003982 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003983 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3984 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 if (r) {
3986 goto error;
3987 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003988 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003989 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003990 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003991 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003992 goto error;
3993 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003994 } else if (!strcmp(sub->name, "default")) {
3995 GETVAL(value, sub, "value");
3996
Radek Krejciac1a52c2016-09-15 14:42:40 +02003997 /* check for duplicity in case of configuration data,
3998 * in case of status data duplicities are allowed */
3999 if (llist->flags & LYS_CONFIG_W) {
4000 for (r = 0; r < llist->dflt_size; r++) {
4001 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004002 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004003 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004004 goto error;
4005 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004006 }
4007 }
4008 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004010 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004011
Radek Krejcicbb473e2016-09-16 14:48:32 +02004012 /* finalize type parsing */
4013 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4014 llist->type.der = NULL;
4015 goto error;
4016 }
4017
Radek Krejcid5a5c282016-08-15 15:38:08 +02004018 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004019 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004020 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004021 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4022 goto error;
4023 }
4024
4025 /* check default value (if not defined, there still could be some restrictions
4026 * that need to be checked against a default value from a derived type) */
4027 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004028 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4029 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004030 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004031 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004032 }
4033
Michal Vasko508a50d2016-09-07 14:50:33 +02004034 /* check XPath dependencies */
4035 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4036 goto error;
4037 }
4038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004039 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004040
4041error:
4042
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004043 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004046}
4047
Michal Vasko0d343d12015-08-24 14:57:36 +02004048/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004049static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004050read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004051 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004052{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004053 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004054 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004055 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004056 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004057 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004059 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004060 char *auxs;
4061 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004063 /* init */
4064 memset(&root, 0, sizeof root);
4065 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004067 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004068 if (!list) {
4069 LOGMEM;
4070 return NULL;
4071 }
Radek Krejci76512572015-08-04 09:47:08 +02004072 list->nodetype = LYS_LIST;
4073 list->prev = (struct lys_node *)list;
4074 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004075
Michal Vaskoe022a562016-09-27 14:24:15 +02004076 if (read_yin_common(module, parent, retval, yin,
4077 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
4078 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004079 goto error;
4080 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004081
Radek Krejcia9544502015-08-14 08:24:29 +02004082 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4083
Radek Krejcic189a952016-07-11 15:27:07 +02004084 /* insert the node into the schema tree */
4085 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4086 goto error;
4087 }
4088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004089 /* process list's specific children */
4090 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004091 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4092 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004093 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004094 continue;
4095 }
4096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004097 /* data statements */
4098 if (!strcmp(sub->name, "container") ||
4099 !strcmp(sub->name, "leaf-list") ||
4100 !strcmp(sub->name, "leaf") ||
4101 !strcmp(sub->name, "list") ||
4102 !strcmp(sub->name, "choice") ||
4103 !strcmp(sub->name, "uses") ||
4104 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004105 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004106 !strcmp(sub->name, "action") ||
4107 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004108 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004109 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004111 /* array counters */
4112 } else if (!strcmp(sub->name, "key")) {
4113 /* check cardinality 0..1 */
4114 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004115 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004116 goto error;
4117 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004119 /* count the number of keys */
4120 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004121 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004122 while ((value = strpbrk(value, " \t\n"))) {
4123 list->keys_size++;
4124 while (isspace(*value)) {
4125 value++;
4126 }
4127 }
4128 list->keys_size++;
4129 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004130 if (!list->keys) {
4131 LOGMEM;
4132 goto error;
4133 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004134 } else if (!strcmp(sub->name, "unique")) {
4135 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004136 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004137 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004138 } else if (!strcmp(sub->name, "typedef")) {
4139 c_tpdf++;
4140 } else if (!strcmp(sub->name, "must")) {
4141 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004142 } else if (!strcmp(sub->name, "if-feature")) {
4143 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 /* optional stetments */
4146 } else if (!strcmp(sub->name, "ordered-by")) {
4147 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004148 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 goto error;
4150 }
4151 /* just checking the flags in llist is not sufficient, we would
4152 * allow multiple ordered-by statements with the "system" value
4153 */
4154 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004155
Radek Krejci1574a8d2015-08-03 14:16:52 +02004156 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4158 * state data
4159 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004160 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 continue;
4162 }
Radek Krejci345ad742015-06-03 11:04:18 +02004163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004164 GETVAL(value, sub, "value");
4165 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004166 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004167 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004168 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004169 goto error;
4170 }
4171 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004172 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004173 } else if (!strcmp(sub->name, "min-elements")) {
4174 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004175 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004176 goto error;
4177 }
4178 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 GETVAL(value, sub, "value");
4181 while (isspace(value[0])) {
4182 value++;
4183 }
Radek Krejci345ad742015-06-03 11:04:18 +02004184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 /* convert it to uint32_t */
4186 errno = 0;
4187 auxs = NULL;
4188 val = strtoul(value, &auxs, 10);
4189 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004190 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004191 goto error;
4192 }
4193 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004194 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004195 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004196 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004197 lyxml_free(module->ctx, sub);
4198 goto error;
4199 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004200 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004201 } else if (!strcmp(sub->name, "max-elements")) {
4202 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004203 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004204 goto error;
4205 }
4206 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004208 GETVAL(value, sub, "value");
4209 while (isspace(value[0])) {
4210 value++;
4211 }
Radek Krejci345ad742015-06-03 11:04:18 +02004212
Radek Krejci0d7b2472016-02-12 11:11:03 +01004213 if (!strcmp(value, "unbounded")) {
4214 list->max = 0;;
4215 } else {
4216 /* convert it to uint32_t */
4217 errno = 0;
4218 auxs = NULL;
4219 val = strtoul(value, &auxs, 10);
4220 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004221 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004222 goto error;
4223 }
4224 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004225 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004226 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004227 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004228 goto error;
4229 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004231 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004232 } else if (!strcmp(sub->name, "when")) {
4233 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004234 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004235 goto error;
4236 }
4237
4238 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004239 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004240 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004241 goto error;
4242 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004243 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004244 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004245 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004246 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004247 }
4248 }
Radek Krejci345ad742015-06-03 11:04:18 +02004249
Michal Vaskoe022a562016-09-27 14:24:15 +02004250 /* check - if list is configuration, key statement is mandatory
4251 * (but only if we are not in a grouping or augment, then the check is deferred) */
4252 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01004253 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004254 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255 goto error;
4256 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004258 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4259 if (c_tpdf) {
4260 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004261 if (!list->tpdf) {
4262 LOGMEM;
4263 goto error;
4264 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004265 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004266 if (c_must) {
4267 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004268 if (!list->must) {
4269 LOGMEM;
4270 goto error;
4271 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004272 }
4273 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004274 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4275 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004276 LOGMEM;
4277 goto error;
4278 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004279 }
Radek Krejci73adb602015-07-02 18:07:40 +02004280 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004281 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004282 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4283 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004284 if (r) {
4285 goto error;
4286 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004287 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004288 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004289 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004290 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004291 goto error;
4292 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004293 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004294 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4295 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004296 if (r) {
4297 goto error;
4298 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 }
4300 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 /* last part - process data nodes */
4303 LY_TREE_FOR_SAFE(root.child, next, sub) {
4304 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004305 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004307 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004309 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004310 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004311 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004312 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004313 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004314 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004315 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004316 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004317 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004318 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004319 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004320 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004321 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004322 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004323 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004324 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004325 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004326 } else {
4327 LOGINT;
4328 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004329 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004330 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 goto error;
4332 }
Radek Krejci73adb602015-07-02 18:07:40 +02004333
Michal Vasko345da0a2015-12-02 10:35:55 +01004334 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004335 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004336
Radek Krejci5c08a992016-11-02 13:30:04 +01004337 if (list->keys_str) {
4338 /* check that we are not in grouping */
4339 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
4340 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004341 goto error;
4342 }
4343 } /* 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 +02004344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004345 /* process unique statements */
4346 if (c_uniq) {
4347 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004348 if (!list->unique) {
4349 LOGMEM;
4350 goto error;
4351 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004352
Radek Krejci461efb92016-02-12 15:52:18 +01004353 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4354 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4355 list->unique_size++;
4356 if (r) {
4357 goto error;
4358 }
4359
4360 lyxml_free(module->ctx, sub);
4361 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004363
Michal Vasko508a50d2016-09-07 14:50:33 +02004364 /* check XPath dependencies */
4365 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4366 goto error;
4367 }
4368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004369 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004370
4371error:
4372
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004373 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004375 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 }
4377 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004378 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004379 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004381 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004382}
4383
Michal Vasko0d343d12015-08-24 14:57:36 +02004384/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004385static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004386read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004387 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004388{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004389 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004390 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004391 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004392 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004393 const char *value;
4394 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004395 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004397 /* init */
4398 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004401 if (!cont) {
4402 LOGMEM;
4403 return NULL;
4404 }
Radek Krejci76512572015-08-04 09:47:08 +02004405 cont->nodetype = LYS_CONTAINER;
4406 cont->prev = (struct lys_node *)cont;
4407 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004408
Michal Vaskoe022a562016-09-27 14:24:15 +02004409 if (read_yin_common(module, parent, retval, yin,
4410 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE)
4411 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004412 goto error;
4413 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004414
Radek Krejcia9544502015-08-14 08:24:29 +02004415 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4416
Radek Krejcic189a952016-07-11 15:27:07 +02004417 /* insert the node into the schema tree */
4418 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4419 goto error;
4420 }
4421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 /* process container's specific children */
4423 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02004424 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004425 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004426 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004427 continue;
4428 }
4429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004430 if (!strcmp(sub->name, "presence")) {
4431 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004432 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 goto error;
4434 }
4435 GETVAL(value, sub, "value");
4436 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004437
Michal Vasko345da0a2015-12-02 10:35:55 +01004438 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004439 } else if (!strcmp(sub->name, "when")) {
4440 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004441 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004442 goto error;
4443 }
4444
4445 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004446 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004447 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004448 goto error;
4449 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004450 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 /* data statements */
4453 } else if (!strcmp(sub->name, "container") ||
4454 !strcmp(sub->name, "leaf-list") ||
4455 !strcmp(sub->name, "leaf") ||
4456 !strcmp(sub->name, "list") ||
4457 !strcmp(sub->name, "choice") ||
4458 !strcmp(sub->name, "uses") ||
4459 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004460 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004461 !strcmp(sub->name, "action") ||
4462 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004463 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004464 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 /* array counters */
4467 } else if (!strcmp(sub->name, "typedef")) {
4468 c_tpdf++;
4469 } else if (!strcmp(sub->name, "must")) {
4470 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004471 } else if (!strcmp(sub->name, "if-feature")) {
4472 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004474 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004475 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 }
4477 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004478
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4480 if (c_tpdf) {
4481 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004482 if (!cont->tpdf) {
4483 LOGMEM;
4484 goto error;
4485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486 }
4487 if (c_must) {
4488 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004489 if (!cont->must) {
4490 LOGMEM;
4491 goto error;
4492 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004494 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004495 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4496 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004497 LOGMEM;
4498 goto error;
4499 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004500 }
Radek Krejci800af702015-06-02 13:46:01 +02004501
Radek Krejci73adb602015-07-02 18:07:40 +02004502 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004504 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4505 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 if (r) {
4507 goto error;
4508 }
4509 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004510 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4511 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 if (r) {
4513 goto error;
4514 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004515 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004516 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004517 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004518 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004519 goto error;
4520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 /* last part - process data nodes */
4525 LY_TREE_FOR_SAFE(root.child, next, sub) {
4526 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004527 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004529 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004531 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004533 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004535 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004537 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004539 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004541 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004542 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004543 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004544 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004545 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004546 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004547 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004548 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004549 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 goto error;
4551 }
Radek Krejci73adb602015-07-02 18:07:40 +02004552
Michal Vasko345da0a2015-12-02 10:35:55 +01004553 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004555
Michal Vasko508a50d2016-09-07 14:50:33 +02004556 /* check XPath dependencies */
4557 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4558 goto error;
4559 }
4560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004562
4563error:
4564
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004565 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004567 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004571}
4572
Michal Vasko0d343d12015-08-24 14:57:36 +02004573/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004574static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004575read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004576 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004577{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004579 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004580 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004581 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 int r;
4583 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 /* init */
4586 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004589 if (!grp) {
4590 LOGMEM;
4591 return NULL;
4592 }
Radek Krejci76512572015-08-04 09:47:08 +02004593 grp->nodetype = LYS_GROUPING;
4594 grp->prev = (struct lys_node *)grp;
4595 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004596
Radek Krejci5c08a992016-11-02 13:30:04 +01004597 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE )) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 goto error;
4599 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004600
Radek Krejcia9544502015-08-14 08:24:29 +02004601 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4602
Radek Krejcic189a952016-07-11 15:27:07 +02004603 /* insert the node into the schema tree */
4604 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4605 goto error;
4606 }
4607
Radek Krejci1d82ef62015-08-07 14:44:40 +02004608 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004609 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4610 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004611 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004612 continue;
4613 }
4614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 /* data statements */
4616 if (!strcmp(sub->name, "container") ||
4617 !strcmp(sub->name, "leaf-list") ||
4618 !strcmp(sub->name, "leaf") ||
4619 !strcmp(sub->name, "list") ||
4620 !strcmp(sub->name, "choice") ||
4621 !strcmp(sub->name, "uses") ||
4622 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004623 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02004624 !strcmp(sub->name, "action") ||
4625 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004626 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004627 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 /* array counters */
4630 } else if (!strcmp(sub->name, "typedef")) {
4631 c_tpdf++;
4632 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004633 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 goto error;
4635 }
4636 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4639 if (c_tpdf) {
4640 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004641 if (!grp->tpdf) {
4642 LOGMEM;
4643 goto error;
4644 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004646 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004647 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4648 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004649 if (r) {
4650 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004655 if (!root.child) {
4656 LOGWRN("Grouping \"%s\" without children.", retval->name);
4657 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 LY_TREE_FOR_SAFE(root.child, next, sub) {
4659 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004660 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004662 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004664 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004666 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004668 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004670 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004672 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004674 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004675 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004676 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004677 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004678 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02004679 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004680 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004682 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 goto error;
4684 }
Radek Krejci73adb602015-07-02 18:07:40 +02004685
Michal Vasko345da0a2015-12-02 10:35:55 +01004686 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004687 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004690
4691error:
4692
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004693 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004695 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004696 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004699}
4700
Michal Vasko0d343d12015-08-24 14:57:36 +02004701/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004702static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004703read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02004704 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004705{
Radek Krejcie0674f82015-06-15 13:58:51 +02004706 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004707 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004708 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004709 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004710 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004711 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004712
Radek Krejcie0674f82015-06-15 13:58:51 +02004713 /* init */
4714 memset(&root, 0, sizeof root);
4715
Michal Vasko38d01f72015-06-15 09:41:06 +02004716 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004717 if (!inout) {
4718 LOGMEM;
4719 return NULL;
4720 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004721 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004722
4723 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004724 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004725 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004726 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004727 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004728 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004729 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004730 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004731 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004732 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004733 }
4734
Radek Krejci76512572015-08-04 09:47:08 +02004735 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004736
Radek Krejci6a113852015-07-03 16:04:20 +02004737 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004738 goto error;
4739 }
4740
Radek Krejcia9544502015-08-14 08:24:29 +02004741 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4742
Radek Krejcic189a952016-07-11 15:27:07 +02004743 /* insert the node into the schema tree */
4744 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4745 goto error;
4746 }
4747
Michal Vasko38d01f72015-06-15 09:41:06 +02004748 /* data statements */
4749 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004750 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4751 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004752 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004753 continue;
4754 }
4755
Michal Vasko38d01f72015-06-15 09:41:06 +02004756 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 !strcmp(sub->name, "leaf-list") ||
4758 !strcmp(sub->name, "leaf") ||
4759 !strcmp(sub->name, "list") ||
4760 !strcmp(sub->name, "choice") ||
4761 !strcmp(sub->name, "uses") ||
4762 !strcmp(sub->name, "grouping") ||
4763 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004764 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004765 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004768 } else if (!strcmp(sub->name, "typedef")) {
4769 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004770
Radek Krejci1a31efe2016-07-29 11:04:16 +02004771 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004772 c_must++;
4773
Michal Vasko38d01f72015-06-15 09:41:06 +02004774 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004775 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004776 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004777 }
4778 }
4779
4780 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4781 if (c_tpdf) {
4782 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004783 if (!inout->tpdf) {
4784 LOGMEM;
4785 goto error;
4786 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004787 }
Radek Krejci19332802016-07-29 10:39:46 +02004788 if (c_must) {
4789 inout->must = calloc(c_must, sizeof *inout->must);
4790 if (!inout->must) {
4791 LOGMEM;
4792 goto error;
4793 }
4794 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004795
Radek Krejci73adb602015-07-02 18:07:40 +02004796 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004797 if (!strcmp(sub->name, "must")) {
4798 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4799 inout->must_size++;
4800 if (r) {
4801 goto error;
4802 }
4803 } else { /* typedef */
4804 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4805 inout->tpdf_size++;
4806 if (r) {
4807 goto error;
4808 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004809 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004810 }
4811
4812 /* last part - process data nodes */
4813 LY_TREE_FOR_SAFE(root.child, next, sub) {
4814 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004815 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004816 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004817 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004818 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004819 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004820 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004821 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004822 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004823 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004824 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004825 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004826 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004827 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004828 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004829 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004830 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004831 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004832 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004833 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004834 goto error;
4835 }
Radek Krejci73adb602015-07-02 18:07:40 +02004836
Michal Vasko345da0a2015-12-02 10:35:55 +01004837 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004838 }
4839
Michal Vasko508a50d2016-09-07 14:50:33 +02004840 /* check XPath dependencies */
4841 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4842 goto error;
4843 }
4844
Michal Vasko38d01f72015-06-15 09:41:06 +02004845 return retval;
4846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004848
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004849 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004850 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004851 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004852 }
4853
4854 return NULL;
4855}
4856
Michal Vasko0d343d12015-08-24 14:57:36 +02004857/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004858static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004859read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02004860 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004861{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004862 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004863 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004864 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004865 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004866 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004867 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004868
Michal Vasko6bb7fc12016-09-21 14:17:22 +02004869 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004870 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02004871 return NULL;
4872 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004873
Michal Vaskoc6551b32015-06-16 10:51:43 +02004874 memset(&root, 0, sizeof root);
4875
Michal Vasko0ea41032015-06-16 08:53:55 +02004876 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004877 if (!notif) {
4878 LOGMEM;
4879 return NULL;
4880 }
Radek Krejci76512572015-08-04 09:47:08 +02004881 notif->nodetype = LYS_NOTIF;
4882 notif->prev = (struct lys_node *)notif;
4883 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004884
Radek Krejci6a113852015-07-03 16:04:20 +02004885 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004886 goto error;
4887 }
4888
Radek Krejcia9544502015-08-14 08:24:29 +02004889 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4890
Radek Krejcic189a952016-07-11 15:27:07 +02004891 /* insert the node into the schema tree */
4892 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4893 goto error;
4894 }
4895
Michal Vasko0ea41032015-06-16 08:53:55 +02004896 /* process rpc's specific children */
4897 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004898 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4899 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004900 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004901 continue;
4902 }
4903
Michal Vasko0ea41032015-06-16 08:53:55 +02004904 /* data statements */
4905 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 !strcmp(sub->name, "leaf-list") ||
4907 !strcmp(sub->name, "leaf") ||
4908 !strcmp(sub->name, "list") ||
4909 !strcmp(sub->name, "choice") ||
4910 !strcmp(sub->name, "uses") ||
4911 !strcmp(sub->name, "grouping") ||
4912 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004913 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004914 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004917 } else if (!strcmp(sub->name, "typedef")) {
4918 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004919 } else if (!strcmp(sub->name, "if-feature")) {
4920 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004921 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004922 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004923 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004924 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004925 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004926 }
4927 }
4928
4929 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4930 if (c_tpdf) {
4931 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004932 if (!notif->tpdf) {
4933 LOGMEM;
4934 goto error;
4935 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004936 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004937 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004938 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4939 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004940 LOGMEM;
4941 goto error;
4942 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004943 }
Radek Krejci19332802016-07-29 10:39:46 +02004944 if (c_must) {
4945 notif->must = calloc(c_must, sizeof *notif->must);
4946 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004947 LOGMEM;
4948 goto error;
4949 }
4950 }
4951
Radek Krejci73adb602015-07-02 18:07:40 +02004952 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004953 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004954 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4955 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004956 if (r) {
4957 goto error;
4958 }
Radek Krejci96299152016-06-22 10:17:50 +02004959 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004960 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004961 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004962 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004963 goto error;
4964 }
Radek Krejci19332802016-07-29 10:39:46 +02004965 } else if (!strcmp(sub->name, "must")) {
4966 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4967 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02004968 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004969 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004970 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004971 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004972 }
4973
4974 /* last part - process data nodes */
4975 LY_TREE_FOR_SAFE(root.child, next, sub) {
4976 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004977 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004978 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004979 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004980 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004981 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004982 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004983 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004984 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004985 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004986 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004987 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004988 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004989 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004990 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004991 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004992 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004993 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004994 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004995 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004996 goto error;
4997 }
Radek Krejci73adb602015-07-02 18:07:40 +02004998
Michal Vasko345da0a2015-12-02 10:35:55 +01004999 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005000 }
5001
Michal Vasko508a50d2016-09-07 14:50:33 +02005002 /* check XPath dependencies */
5003 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5004 goto error;
5005 }
5006
Michal Vasko0ea41032015-06-16 08:53:55 +02005007 return retval;
5008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005009error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005010
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005011 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005012 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005013 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005014 }
5015
5016 return NULL;
5017}
5018
Michal Vasko0d343d12015-08-24 14:57:36 +02005019/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005020static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005021read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005022 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005023{
Radek Krejcie0674f82015-06-15 13:58:51 +02005024 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005025 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005026 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005027 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005028 int r;
Pavol Vican3cb70c72016-09-05 11:32:52 +02005029 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005030
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005031 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005032 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005033 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005034 return NULL;
5035 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005036 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005037 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005038 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005039 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005040 return NULL;
5041 }
5042 }
5043 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005044
Radek Krejcie0674f82015-06-15 13:58:51 +02005045 /* init */
5046 memset(&root, 0, sizeof root);
5047
Michal Vasko38d01f72015-06-15 09:41:06 +02005048 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005049 if (!rpc) {
5050 LOGMEM;
5051 return NULL;
5052 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005053 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005054 rpc->prev = (struct lys_node *)rpc;
5055 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005056
Radek Krejci6a113852015-07-03 16:04:20 +02005057 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005058 goto error;
5059 }
5060
Radek Krejcia9544502015-08-14 08:24:29 +02005061 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5062
Radek Krejcic189a952016-07-11 15:27:07 +02005063 /* insert the node into the schema tree */
5064 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5065 goto error;
5066 }
5067
Michal Vasko38d01f72015-06-15 09:41:06 +02005068 /* process rpc's specific children */
5069 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005070 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5071 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005072 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005073 continue;
5074 }
5075
Michal Vasko38d01f72015-06-15 09:41:06 +02005076 if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005077 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005078 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005079 goto error;
5080 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005081 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005082 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005083 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005084 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005085 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005086 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005087 goto error;
5088 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005089 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005090 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005091 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005093 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005094 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005095 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005096 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005098 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005099 } else if (!strcmp(sub->name, "typedef")) {
5100 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005101 } else if (!strcmp(sub->name, "if-feature")) {
5102 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005103 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005104 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005105 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005106 }
5107 }
5108
5109 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5110 if (c_tpdf) {
5111 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005112 if (!rpc->tpdf) {
5113 LOGMEM;
5114 goto error;
5115 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005116 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005117 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005118 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5119 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005120 LOGMEM;
5121 goto error;
5122 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005123 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005124
Radek Krejci73adb602015-07-02 18:07:40 +02005125 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005126 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005127 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5128 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005129 if (r) {
5130 goto error;
5131 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005132 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005133 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005134 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005135 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005136 goto error;
5137 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005138 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005139 }
5140
5141 /* last part - process data nodes */
5142 LY_TREE_FOR_SAFE(root.child, next, sub) {
5143 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005144 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005145 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005146 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005147 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005148 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005149 goto error;
5150 }
Radek Krejci73adb602015-07-02 18:07:40 +02005151
Michal Vasko345da0a2015-12-02 10:35:55 +01005152 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005153 }
5154
Michal Vasko38d01f72015-06-15 09:41:06 +02005155 return retval;
5156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005157error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005158
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005159 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005160 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005161 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005162 }
5163
5164 return NULL;
5165}
5166
Michal Vasko0d343d12015-08-24 14:57:36 +02005167/* logs directly
5168 *
Radek Krejci74705112015-06-05 10:25:44 +02005169 * resolve - referenced grouping should be bounded to the namespace (resolved)
5170 * only when uses does not appear in grouping. In a case of grouping's uses,
5171 * we just get information but we do not apply augment or refine to it.
5172 */
Radek Krejci76512572015-08-04 09:47:08 +02005173static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005174read_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 +02005175{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005177 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005178 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005179 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005180 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005184 if (!uses) {
5185 LOGMEM;
5186 return NULL;
5187 }
Radek Krejci76512572015-08-04 09:47:08 +02005188 uses->nodetype = LYS_USES;
5189 uses->prev = (struct lys_node *)uses;
5190 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005191
Radek Krejcia9544502015-08-14 08:24:29 +02005192 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005194
Michal Vaskoe0c59842015-09-24 13:52:20 +02005195 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02005196 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 goto error;
5198 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005199
Radek Krejcia9544502015-08-14 08:24:29 +02005200 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5201
Radek Krejcic189a952016-07-11 15:27:07 +02005202 /* insert the node into the schema tree */
5203 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5204 goto error;
5205 }
5206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005208 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005209 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5210 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005211 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005212 continue;
5213 }
5214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005215 if (!strcmp(sub->name, "refine")) {
5216 c_ref++;
5217 } else if (!strcmp(sub->name, "augment")) {
5218 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005219 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005220 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005221 } else if (!strcmp(sub->name, "when")) {
5222 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005223 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005224 goto error;
5225 }
5226
5227 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005228 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005229 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005230 goto error;
5231 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005232 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005234 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005235 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005236 }
5237 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005239 /* process properties with cardinality 0..n */
5240 if (c_ref) {
5241 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005242 if (!uses->refine) {
5243 LOGMEM;
5244 goto error;
5245 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005246 }
5247 if (c_aug) {
5248 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005249 if (!uses->augment) {
5250 LOGMEM;
5251 goto error;
5252 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005254 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005255 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5256 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005257 LOGMEM;
5258 goto error;
5259 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005260 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005261
Radek Krejcia9544502015-08-14 08:24:29 +02005262 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005264 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005265 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005266 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005267 goto error;
5268 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005269 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005270 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5271 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005272 if (r) {
5273 goto error;
5274 }
5275 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005276 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005277 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005278 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005279 goto error;
5280 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 }
5282 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005283
Radek Krejci48464ed2016-03-17 15:44:09 +01005284 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005285 goto error;
5286 }
Radek Krejci74705112015-06-05 10:25:44 +02005287
Michal Vasko508a50d2016-09-07 14:50:33 +02005288 /* check XPath dependencies */
5289 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5290 goto error;
5291 }
5292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005294
5295error:
5296
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005297 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005299 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005300}
5301
Michal Vasko0d343d12015-08-24 14:57:36 +02005302/* logs directly
5303 *
5304 * common code for yin_read_module() and yin_read_submodule()
5305 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005306static int
Radek Krejcic071c542016-01-27 14:57:51 +01005307read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5308 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005309{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005310 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005311 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005312 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005313 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005314 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005315 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01005316 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01005317 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
5318 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
5319 int substmt_group;
5320 /* just remember last substatement for logging */
5321 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005322 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02005323 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 +02005324
Radek Krejcic071c542016-01-27 14:57:51 +01005325 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005326 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005328 /* init */
5329 memset(&root, 0, sizeof root);
5330 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005331 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02005332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 /*
5334 * in the first run, we process elements with cardinality of 1 or 0..1 and
5335 * count elements with cardinality 0..n. Data elements (choices, containers,
5336 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5337 * need have all top-level and groupings already prepared at that time. In
5338 * the middle loop, we process other elements with carinality of 0..n since
5339 * we need to allocate arrays to store them.
5340 */
Michal Vasko5de8a022017-02-08 10:57:26 +01005341 substmt_group = 0;
5342 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005343 LY_TREE_FOR_SAFE(yin->child, next, child) {
5344 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005345 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005346 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005347 continue;
5348 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005349
Radek Krejcic071c542016-01-27 14:57:51 +01005350 if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005351 if (substmt_group > 0) {
5352 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5353 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5354 child->name, substmt_prev);
5355 goto error;
5356 }
5357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005358 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005359 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005360 goto error;
5361 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005362 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005363 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005364 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01005365
5366 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01005367 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005368 if (substmt_group > 0) {
5369 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5370 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5371 child->name, substmt_prev);
5372 goto error;
5373 }
5374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005375 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005376 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005377 goto error;
5378 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005379 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005380 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005381 goto error;
5382 }
5383 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005384 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01005385
5386 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01005387 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005388 if (substmt_group > 0) {
5389 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5390 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5391 child->name, substmt_prev);
5392 goto error;
5393 }
5394
Radek Krejcic071c542016-01-27 14:57:51 +01005395 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005396 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 goto error;
5398 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005399 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005400 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005401 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005402 goto error;
5403 }
Radek Krejcif3886932015-06-04 17:36:06 +02005404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005405 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005406 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005407 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005408 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005409 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005410 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005411 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005412 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005413 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005414 goto error;
5415 }
5416 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005417 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005418 /* check here differs from a generic prefix check, since this prefix
5419 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005420 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005421 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005422 goto error;
5423 }
Radek Krejcic071c542016-01-27 14:57:51 +01005424 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005426 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005427 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005428
Michal Vasko5de8a022017-02-08 10:57:26 +01005429 substmt_prev = "belongs-to";
5430
Radek Krejcieb00f512015-07-01 16:44:58 +02005431 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005432 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005433 if (substmt_group > 1) {
5434 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5435 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5436 child->name, substmt_prev);
5437 goto error;
5438 }
5439 substmt_group = 1;
5440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005441 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01005442
5443 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005444 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005445 if (substmt_group > 3) {
5446 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5447 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5448 child->name, substmt_prev);
5449 goto error;
5450 }
5451 substmt_group = 3;
5452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01005454
5455 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005456 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005457 substmt_group = 4;
5458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005459 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01005460
5461 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005462 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005463 substmt_group = 4;
5464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005465 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01005466
5467 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005468 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005469 if (substmt_group > 1) {
5470 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5471 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5472 child->name, substmt_prev);
5473 goto error;
5474 }
5475 substmt_group = 1;
5476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005477 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01005478
5479 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005480 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005481 substmt_group = 4;
5482
Radek Krejcif5be10f2015-06-16 13:29:36 +02005483 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005484 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005485 lyxml_unlink_elem(ctx, child, 2);
5486 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005487
Michal Vasko5de8a022017-02-08 10:57:26 +01005488 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005489 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005490 substmt_group = 4;
5491
Radek Krejci3cf9e222015-06-18 11:37:50 +02005492 c_ftrs++;
Michal Vasko5de8a022017-02-08 10:57:26 +01005493
5494 substmt_prev = "feature";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005495 } else if (!strcmp(child->name, "deviation")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005496 substmt_group = 4;
5497
Radek Krejcieb00f512015-07-01 16:44:58 +02005498 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005499
Michal Vasko5de8a022017-02-08 10:57:26 +01005500 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005501 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005502 } else if (!strcmp(child->name, "container") ||
5503 !strcmp(child->name, "leaf-list") ||
5504 !strcmp(child->name, "leaf") ||
5505 !strcmp(child->name, "list") ||
5506 !strcmp(child->name, "choice") ||
5507 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005508 !strcmp(child->name, "anyxml") ||
5509 !strcmp(child->name, "rpc") ||
5510 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005511 substmt_group = 4;
5512
Radek Krejcic071c542016-01-27 14:57:51 +01005513 lyxml_unlink_elem(ctx, child, 2);
5514 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005515
Michal Vasko5de8a022017-02-08 10:57:26 +01005516 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005517 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005518 substmt_group = 4;
5519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005520 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005521 lyxml_unlink_elem(ctx, child, 2);
5522 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005523
Michal Vasko5de8a022017-02-08 10:57:26 +01005524 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005525 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005526 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005527 if (substmt_group > 2) {
5528 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5529 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5530 child->name, substmt_prev);
5531 goto error;
5532 }
5533 substmt_group = 2;
5534
Radek Krejcic071c542016-01-27 14:57:51 +01005535 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005536 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005537 goto error;
5538 }
Radek Krejcic071c542016-01-27 14:57:51 +01005539 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005540 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005541 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005542 goto error;
5543 }
Michal Vasko5de8a022017-02-08 10:57:26 +01005544
5545 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005546 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005547 if (substmt_group > 2) {
5548 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5549 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5550 child->name, substmt_prev);
5551 goto error;
5552 }
5553 substmt_group = 2;
5554
Radek Krejcic071c542016-01-27 14:57:51 +01005555 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005556 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005557 goto error;
5558 }
Radek Krejcic071c542016-01-27 14:57:51 +01005559 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005560 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005561 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 goto error;
5563 }
Michal Vasko5de8a022017-02-08 10:57:26 +01005564
5565 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005566 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005567 if (substmt_group > 2) {
5568 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5569 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5570 child->name, substmt_prev);
5571 goto error;
5572 }
5573 substmt_group = 2;
5574
Radek Krejcic071c542016-01-27 14:57:51 +01005575 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005576 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005577 goto error;
5578 }
Radek Krejcic071c542016-01-27 14:57:51 +01005579 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005580 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005581 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005582 goto error;
5583 }
Michal Vasko5de8a022017-02-08 10:57:26 +01005584
5585 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005586 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005587 if (substmt_group > 2) {
5588 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5589 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5590 child->name, substmt_prev);
5591 goto error;
5592 }
5593 substmt_group = 2;
5594
Radek Krejcic071c542016-01-27 14:57:51 +01005595 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005596 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005597 goto error;
5598 }
Radek Krejcic071c542016-01-27 14:57:51 +01005599 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005600 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005601 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005602 goto error;
5603 }
Michal Vasko5de8a022017-02-08 10:57:26 +01005604
5605 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005606 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005607 if (substmt_group > 0) {
5608 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
5609 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
5610 child->name, substmt_prev);
5611 goto error;
5612 }
5613
Radek Krejcic071c542016-01-27 14:57:51 +01005614 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005615 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005616 goto error;
5617 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005618 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005619 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005620 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005621 goto error;
5622 }
Radek Krejcic071c542016-01-27 14:57:51 +01005623 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005624 if (!strcmp(value, "1")) {
5625 if (submodule) {
5626 if (module->version > 1) {
5627 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5628 goto error;
5629 }
5630 } else {
5631 module->version = 1;
5632 }
5633 } else {
5634 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005635 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005636 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5637 goto error;
5638 }
5639 } else {
5640 module->version = 2;
5641 }
5642 }
5643
Michal Vasko345da0a2015-12-02 10:35:55 +01005644 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005645
Michal Vasko5de8a022017-02-08 10:57:26 +01005646 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02005647 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01005648 substmt_group = 4;
5649
Radek Krejci1d82ef62015-08-07 14:44:40 +02005650 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005651
Radek Krejci3d468122015-10-02 13:36:12 +02005652 /* we have the following supported (hardcoded) extensions: */
5653 /* ietf-netconf's get-filter-element-attributes */
5654 if (!strcmp(module->ns, LY_NSNC) &&
5655 !strcmp(value, "get-filter-element-attributes")) {
5656 LOGDBG("NETCONF filter extension found");
5657 /* NACM's default-deny-write and default-deny-all */
5658 } else if (!strcmp(module->ns, LY_NSNACM) &&
5659 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5660 LOGDBG("NACM extension found");
5661 /* other extensions are not supported, so inform about such an extension */
5662 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005663 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005664 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005665 }
Michal Vasko5de8a022017-02-08 10:57:26 +01005666
5667 substmt_prev = "extension";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005668 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005669 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005670 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005671 }
5672 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005673
Radek Krejcic071c542016-01-27 14:57:51 +01005674 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01005675 if (submodule) {
5676 if (!submodule->prefix) {
5677 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
5678 goto error;
5679 }
5680 if (!version_flag) {
5681 /* check version compatibility with the main module */
5682 if (module->version > 1) {
5683 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5684 goto error;
5685 }
5686 }
5687 } else {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005688 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005689 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005690 goto error;
5691 }
5692 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005693 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005694 goto error;
5695 }
5696 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005698 /* allocate arrays for elements with cardinality of 0..n */
5699 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01005700 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01005701 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005702 LOGMEM;
5703 goto error;
5704 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005705 }
5706 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005707 trg->rev = calloc(c_rev, sizeof *trg->rev);
5708 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005709 LOGMEM;
5710 goto error;
5711 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005712 }
5713 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005714 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5715 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005716 LOGMEM;
5717 goto error;
5718 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005719 }
5720 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005721 trg->ident = calloc(c_ident, sizeof *trg->ident);
5722 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005723 LOGMEM;
5724 goto error;
5725 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005726 }
5727 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01005728 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01005729 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005730 LOGMEM;
5731 goto error;
5732 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005733 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005734 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005735 trg->augment = calloc(c_aug, sizeof *trg->augment);
5736 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005737 LOGMEM;
5738 goto error;
5739 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005740 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005741 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005742 trg->features = calloc(c_ftrs, sizeof *trg->features);
5743 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005744 LOGMEM;
5745 goto error;
5746 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005747 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005748 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005749 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5750 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005751 LOGMEM;
5752 goto error;
5753 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005754 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005755
Michal Vasko2f7925f2015-10-21 15:06:56 +02005756 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5757 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005758 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005759 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5760 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005761 if (r) {
5762 goto error;
5763 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005764
Radek Krejci1d82ef62015-08-07 14:44:40 +02005765 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01005766 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
5767 trg->inc_size++;
5768 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005769 goto error;
5770 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005771
Radek Krejci1d82ef62015-08-07 14:44:40 +02005772 } else if (!strcmp(child->name, "revision")) {
5773 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005774 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005775 goto error;
5776 }
Radek Krejcic071c542016-01-27 14:57:51 +01005777 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005778 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005779 for (i = 0; i < trg->rev_size; i++) {
5780 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005781 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5782 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005783 }
5784 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005785
Radek Krejci1d82ef62015-08-07 14:44:40 +02005786 LY_TREE_FOR(child->child, child2) {
5787 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005788 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005789 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005790 goto error;
5791 }
Radek Krejcic071c542016-01-27 14:57:51 +01005792 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5793 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005794 goto error;
5795 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005796 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005797 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005798 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005799 goto error;
5800 }
Radek Krejcic071c542016-01-27 14:57:51 +01005801 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5802 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005803 goto error;
5804 }
5805 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005806 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005807 goto error;
5808 }
5809 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005811 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005812 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005813 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005814 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005815 if (!value) {
5816 LOGMEM;
5817 goto error;
5818 }
Radek Krejcic071c542016-01-27 14:57:51 +01005819 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5820 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005821 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005822
Radek Krejci749190d2016-02-18 16:26:25 +01005823 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005824 value = trg->rev[0].dsc;
5825 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5826 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005827 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005828
Radek Krejci749190d2016-02-18 16:26:25 +01005829 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005830 value = trg->rev[0].ref;
5831 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5832 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005833 }
5834 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005835
Radek Krejcic071c542016-01-27 14:57:51 +01005836 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005837
Radek Krejci1d82ef62015-08-07 14:44:40 +02005838 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005839 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5840 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005841 if (r) {
5842 goto error;
5843 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005844
Radek Krejci1d82ef62015-08-07 14:44:40 +02005845 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005846 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5847 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005848 if (r) {
5849 goto error;
5850 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005851
Radek Krejci1d82ef62015-08-07 14:44:40 +02005852 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005853 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5854 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005855 if (r) {
5856 goto error;
5857 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005858
Radek Krejci1d82ef62015-08-07 14:44:40 +02005859 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005860 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5861 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005862 if (r) {
5863 goto error;
5864 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005865 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005866 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005867
Radek Krejcif5be10f2015-06-16 13:29:36 +02005868 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005869 * refer to them. Submodule's data nodes are stored in the
5870 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005871 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005872 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005873 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005874 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005875 goto error;
5876 }
Radek Krejci74705112015-06-05 10:25:44 +02005877
Michal Vasko345da0a2015-12-02 10:35:55 +01005878 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005879 }
Radek Krejci74705112015-06-05 10:25:44 +02005880
Radek Krejcif5be10f2015-06-16 13:29:36 +02005881 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005882 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005883
Radek Krejci1d82ef62015-08-07 14:44:40 +02005884 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005885 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005886 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005887 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005888 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005889 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005890 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005891 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005892 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005893 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005894 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005895 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005896 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02005897 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
5898 } else if (!strcmp(child->name, "anydata")) {
5899 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005900 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005901 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005902 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005903 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005904 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005905 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005906 goto error;
5907 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005908
Michal Vasko345da0a2015-12-02 10:35:55 +01005909 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005910 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005911
Michal Vasko2f7925f2015-10-21 15:06:56 +02005912 /* ... and finally augments (last, so we can augment our data, for instance) */
5913 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005914 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5915 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005916
Michal Vasko2f7925f2015-10-21 15:06:56 +02005917 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005918 goto error;
5919 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005920 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005921 }
5922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005923 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005924
5925error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005926 /* cleanup */
5927 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005928 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005929 }
5930 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005931 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005932 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005933 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005934 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005935 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005937 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005938}
5939
Michal Vasko0d343d12015-08-24 14:57:36 +02005940/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005941struct lys_submodule *
5942yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005943{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005944 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005945 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005946 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005947
Michal Vasko5a721fd2016-02-16 12:16:48 +01005948 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005949
Radek Krejci722b0072016-02-01 17:09:45 +01005950 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005951 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005952 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005953 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005955 /* check root element */
5956 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005957 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005958 goto error;
5959 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005961 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005962 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005963 goto error;
5964 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005965
Michal Vasko5a721fd2016-02-16 12:16:48 +01005966 submodule = calloc(1, sizeof *submodule);
5967 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005968 LOGMEM;
5969 goto error;
5970 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005971
Michal Vasko5a721fd2016-02-16 12:16:48 +01005972 submodule->ctx = module->ctx;
5973 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5974 submodule->type = 1;
5975 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005976
Michal Vasko5a721fd2016-02-16 12:16:48 +01005977 LOGVRB("Reading submodule \"%s\".", submodule->name);
5978 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005979 goto error;
5980 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005982 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005983 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005984
Michal Vasko5a721fd2016-02-16 12:16:48 +01005985 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005986 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005987
5988error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005989 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005990 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005991 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005992
Michal Vasko5a721fd2016-02-16 12:16:48 +01005993 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005994 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005995 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005996 }
5997
Michal Vasko5a721fd2016-02-16 12:16:48 +01005998 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005999
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006000 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6001 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006002 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006003 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006004}
6005
Michal Vasko0d343d12015-08-24 14:57:36 +02006006/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006007struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01006008yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006009{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006010 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006011 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006012 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006013 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006014
Radek Krejcic071c542016-01-27 14:57:51 +01006015 unres = calloc(1, sizeof *unres);
6016 if (!unres) {
6017 LOGMEM;
6018 return NULL;
6019 }
6020
Radek Krejci722b0072016-02-01 17:09:45 +01006021 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006022 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01006023 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006024 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006026 /* check root element */
6027 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02006028 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006029 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
6030 } else {
6031 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02006032 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006033 goto error;
6034 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006036 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006037 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006038 goto error;
6039 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006041 module = calloc(1, sizeof *module);
6042 if (!module) {
6043 LOGMEM;
6044 goto error;
6045 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006047 module->ctx = ctx;
6048 module->name = lydict_insert(ctx, value, strlen(value));
6049 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02006050 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02006051
Michal Vasko9f258e42016-02-11 11:36:27 +01006052 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01006053 if (read_sub_module(module, NULL, yin, unres)) {
6054 goto error;
6055 }
6056
6057 /* resolve rest of unres items */
6058 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006059 goto error;
6060 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006061
Radek Krejciff4874d2016-03-07 12:30:50 +01006062 if (revision) {
6063 /* check revision of the parsed model */
6064 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01006065 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
6066 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01006067 goto error;
6068 }
6069 }
6070
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006071 /* check correctness of includes */
6072 if (lyp_check_include_missing(module)) {
6073 goto error;
6074 }
6075
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006076 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006077 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006078 }
Radek Krejci63a91a92015-07-29 13:31:04 +02006079
Radek Krejci27fe55e2016-09-13 17:13:35 +02006080 if (module->deviation_size && !module->implemented) {
6081 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
6082 /* deviations always causes target to be made implemented,
6083 * but augents and leafrefs not, so we have to apply them now */
6084 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02006085 goto error;
6086 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006087 }
6088
Michal Vasko345da0a2015-12-02 10:35:55 +01006089 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01006090 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01006091 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006092 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006093
6094error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006095 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01006096 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01006097 unres_schema_free(module, &unres);
6098
6099 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006100 if (ly_vecode != LYVE_SUBMODULE) {
6101 LOGERR(ly_errno, "Module parsing failed.");
6102 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01006103 return NULL;
6104 }
6105
6106 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006107
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006108 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01006109 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006110 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006111}