blob: f3f06762c224c3965cf3d1e9daa8a2d8a5b41bb3 [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
Radek Krejcib8048692015-08-05 13:36:34 +020047static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020048
Radek Krejcib8048692015-08-05 13:36:34 +020049static 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 +020050 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020051static 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 +020052 int valid_config, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020053static 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 +020054 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020055static 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 +020056 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020057static 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 +020058 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020059static 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 +020060 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020061static 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 +020062 int valid_config, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020063static 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 +020064 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020065static 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 +020066 int valid_config, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020067static 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 +020068 struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020069static 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 +020070 struct unres_schema *unres);
Michal Vaskof02e3742015-08-05 16:27:02 +020071static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020072
Michal Vasko0d343d12015-08-24 14:57:36 +020073/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020074static const char *
75read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020076{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020077 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 /* there should be <text> child */
80 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010081 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010082 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010083 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084 } else if (node->child->content) {
85 len = strlen(node->child->content);
86 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010087 } else {
88 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020090}
91
Radek Krejcie534c132016-11-23 13:32:31 +010092/*
93 * yin - the provided XML subtree is unlinked
94 */
95static int
Radek Krejci0aa821a2016-12-08 11:21:35 +010096fill_yin_ext(void *parent, LYEXT_PAR parent_type, struct lys_module *module, struct lyxml_elem *yin,
Radek Krejcie534c132016-11-23 13:32:31 +010097 struct lys_ext_instance **ext, struct unres_schema *unres)
98{
99 struct unres_ext *info;
100
101 info = malloc(sizeof *info);
102 lyxml_unlink(module->ctx, yin);
103 info->data.yin = yin;
104 info->datatype = LYS_IN_YIN;
105 info->parent = parent;
106 info->parent_type = parent_type;
Radek Krejci80c6b442017-01-04 16:21:13 +0100107 /* TODO - extensions in substatements support */
108 info->substmt = 0;
109 info->substmt_index = 0;
Radek Krejcie534c132016-11-23 13:32:31 +0100110
111 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
112 return EXIT_FAILURE;
113 }
114
115 return EXIT_SUCCESS;
116}
117
Michal Vasko0d343d12015-08-24 14:57:36 +0200118/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200119static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200120fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
121 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100122{
123 int r;
124 const char *value;
125
126 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200127
128 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
129 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200130error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100131 return EXIT_FAILURE;
132 }
133
Michal Vasko56d082c2016-10-25 14:00:42 +0200134 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100135 return EXIT_FAILURE;
136 }
137
Radek Krejci9de2c042016-10-19 16:53:06 +0200138 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100139 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200140 if (r) {
141 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100142 }
143
Radek Krejci9ff0a922016-07-14 13:08:05 +0200144 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100145}
146
147/* logs directly */
148static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200149fill_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 +0200150{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200151 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200152 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200153 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100154 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200155
Michal Vasko4cfcd252015-08-03 14:31:10 +0200156 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100157 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200158
Radek Krejci76512572015-08-04 09:47:08 +0200159 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200160 return EXIT_FAILURE;
161 }
Radek Krejci04581c62015-05-22 21:24:00 +0200162
Pavol Vicand6cda452016-07-13 15:08:29 +0200163 if (dup_identities_check(ident->name, module)) {
164 return EXIT_FAILURE;
165 }
166
Radek Krejcie534c132016-11-23 13:32:31 +0100167 LY_TREE_FOR(yin->child, node) {
168 if (strcmp(node->ns->value, LY_NSYIN)) {
169 /* extension */
170 c_ext++;
171 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200172 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100173 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200174 return EXIT_FAILURE;
175 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200176 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100177
Radek Krejci018f1f52016-08-03 16:01:20 +0200178 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
179 c_ftrs++;
180
181 } else {
182 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
183 return EXIT_FAILURE;
184 }
185 }
186
187 if (c_base) {
188 ident->base_size = 0;
189 ident->base = calloc(c_base, sizeof *ident->base);
190 if (!ident->base) {
191 LOGMEM;
192 return EXIT_FAILURE;
193 }
194 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200195 if (c_ftrs) {
196 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
197 if (!ident->iffeature) {
198 LOGMEM;
199 return EXIT_FAILURE;
200 }
201 }
Radek Krejcie534c132016-11-23 13:32:31 +0100202 if (c_ext) {
203 ident->ext = calloc(c_ext, sizeof *ident->ext);
204 if (!ident->ext) {
205 LOGMEM;
206 return EXIT_FAILURE;
207 }
208 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200209
Radek Krejcie534c132016-11-23 13:32:31 +0100210 LY_TREE_FOR_SAFE(yin->child, next, node) {
211 if (strcmp(node->ns->value, LY_NSYIN)) {
212 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +0100213 rc = fill_yin_ext(ident, LYEXT_PAR_IDENT, module, node, &ident->ext[ident->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +0100214 ident->ext_size++;
215 if (rc) {
216 goto error;
217 }
218 } else if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200219 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100220 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100221 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200222 return EXIT_FAILURE;
223 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100224
Radek Krejci48464ed2016-03-17 15:44:09 +0100225 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100226 lydict_remove(module->ctx, value);
227 return EXIT_FAILURE;
228 }
229 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200230 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200231 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200232 ident->iffeature_size++;
233 if (rc) {
234 return EXIT_FAILURE;
235 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200236 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200237 }
Radek Krejci04581c62015-05-22 21:24:00 +0200238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200239 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200240
241error:
242 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200243}
244
Michal Vasko0d343d12015-08-24 14:57:36 +0200245/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200246static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200247read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200248{
Radek Krejci73adb602015-07-02 18:07:40 +0200249 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200250 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200251
Radek Krejci73adb602015-07-02 18:07:40 +0200252 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200253 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
254 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200255 continue;
256 }
257
Radek Krejci41726f92015-06-19 13:11:05 +0200258 if (!strcmp(child->name, "description")) {
259 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100260 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200261 return EXIT_FAILURE;
262 }
263 restr->dsc = read_yin_subnode(ctx, child, "text");
264 if (!restr->dsc) {
265 return EXIT_FAILURE;
266 }
267 } else if (!strcmp(child->name, "reference")) {
268 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100269 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200270 return EXIT_FAILURE;
271 }
272 restr->ref = read_yin_subnode(ctx, child, "text");
273 if (!restr->ref) {
274 return EXIT_FAILURE;
275 }
276 } else if (!strcmp(child->name, "error-app-tag")) {
277 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100278 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200279 return EXIT_FAILURE;
280 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200281 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200282 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200283 } else if (!strcmp(child->name, "error-message")) {
284 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100285 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200286 return EXIT_FAILURE;
287 }
288 restr->emsg = read_yin_subnode(ctx, child, "value");
289 if (!restr->emsg) {
290 return EXIT_FAILURE;
291 }
292 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100293 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200294 return EXIT_FAILURE;
295 }
Radek Krejci41726f92015-06-19 13:11:05 +0200296 }
297
298 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200299
300error:
301 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200302}
303
Michal Vasko88c29542015-11-27 14:57:53 +0100304/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
305int
Radek Krejcib8048692015-08-05 13:36:34 +0200306fill_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 +0200307 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200308{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200309 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200310 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100311 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200312 struct lys_restr **restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200313 struct lys_type_bit bit, *bits_sc = NULL;
314 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200315 struct lys_type *dertype;
Radek Krejcie534c132016-11-23 13:32:31 +0100316 int i, j, rc, val_set, c_ftrs, c_ext = 0;
Radek Krejcidc008d72016-02-17 13:12:14 +0100317 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200319 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200320 size_t len;
321 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200322
Radek Krejcie534c132016-11-23 13:32:31 +0100323 /* init */
324 memset(&exts, 0, sizeof exts);
325
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200326 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100327 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200328 if (!value) {
329 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200330 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200331
332 i = parse_identifier(value);
333 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100334 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100335 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200336 goto error;
337 }
338 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100339 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200340 if (value[i]) {
341 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100342 name += i;
343 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100344 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100345 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200346 goto error;
347 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200348 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100349 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200350 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200351
Radek Krejci225376f2016-02-16 17:36:22 +0100352 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200353 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100354 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200355 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200356 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100357
358 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200359 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200360 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200361 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100362 ret = EXIT_FAILURE;
363 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200364 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200365 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200366
Radek Krejci9b6aad22016-09-20 15:55:51 +0200367 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200368 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200369 * 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 +0200370 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
371 if (siter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +0100372#if __BYTE_ORDER == __LITTLE_ENDIAN
373 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]) {
Radek Krejcic13db382016-08-16 10:52:42 +0200374 LOGINT;
375 goto error;
376 }
Radek Krejci6ff885d2017-01-03 14:06:22 +0100377 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]--;
378#else
379 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]) {
380 LOGINT;
381 goto error;
382 }
383 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]--;
384#endif
Radek Krejcic13db382016-08-16 10:52:42 +0200385 } else {
386 LOGINT;
387 goto error;
388 }
389 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200390 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200391
Radek Krejcicf509982015-12-15 09:22:44 +0100392 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100393 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100394 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100395 return -1;
396 }
397
Radek Krejcie534c132016-11-23 13:32:31 +0100398 /* parse extension instances */
399 LY_TREE_FOR_SAFE(yin->child, next, node) {
400 if (!node->ns) {
401 /* garbage */
402 lyxml_free(module->ctx, node);
403 continue;
404 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
405 /* YANG (YIN) statements - process later */
406 continue;
407 }
408
409 lyxml_unlink_elem(module->ctx, node, 2);
410 lyxml_add_child(module->ctx, &exts, node);
411 c_ext++;
412 }
413 if (c_ext) {
414 type->ext = calloc(c_ext, sizeof *type->ext);
415 if (!type->ext) {
416 LOGMEM;
417 goto error;
418 }
419 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci0aa821a2016-12-08 11:21:35 +0100420 rc = fill_yin_ext(type, LYEXT_PAR_TYPE, module, node, &type->ext[type->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +0100421 type->ext_size++;
422 if (rc) {
423 goto error;
424 }
425 }
426 }
427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200428 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200429 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200430 /* RFC 6020 9.7.4 - bit */
431
432 /* get bit specifications, at least one must be present */
433 LY_TREE_FOR_SAFE(yin->child, next, node) {
434 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200435 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200436 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100437 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200438 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200439 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200440 }
441 }
Radek Krejcie663e012016-08-01 17:12:34 +0200442 dertype = &type->der->type;
443 if (!dertype->der) {
444 if (!type->info.bits.count) {
445 /* type is derived directly from buit-in bits type and bit statement is required */
446 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
447 goto error;
448 }
449 } else {
450 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
451 if (module->version < 2 && type->info.bits.count) {
452 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
453 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
454 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200455 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200456 goto error;
457 }
Radek Krejciac781922015-07-09 15:35:14 +0200458 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200459
460 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100461 if (!type->info.bits.bit) {
462 LOGMEM;
463 goto error;
464 }
Radek Krejci73adb602015-07-02 18:07:40 +0200465 p = 0;
466 i = -1;
467 LY_TREE_FOR(yin->child, next) {
468 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200469 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200470
471 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100472 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100473 goto error;
474 }
475
Radek Krejci994b6f62015-06-18 16:47:27 +0200476 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200477 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200478 type->info.bits.count = i + 1;
479 goto error;
480 }
481
Radek Krejcie663e012016-08-01 17:12:34 +0200482 if (!dertype->der) { /* directly derived type from bits built-in type */
483 /* check the name uniqueness */
484 for (j = 0; j < i; j++) {
485 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
486 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
487 type->info.bits.count = i + 1;
488 goto error;
489 }
490 }
491 } else {
492 /* restricted bits type - the name MUST be used in the base type */
493 bits_sc = dertype->info.bits.bit;
494 for (j = 0; j < dertype->info.bits.count; j++) {
495 if (ly_strequal(bits_sc[j].name, value, 1)) {
496 break;
497 }
498 }
499 if (j == dertype->info.bits.count) {
500 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200501 type->info.bits.count = i + 1;
502 goto error;
503 }
504 }
505
Radek Krejcie663e012016-08-01 17:12:34 +0200506
Radek Krejci0d70c372015-07-02 16:23:10 +0200507 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200508 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200509 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
510 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200511 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200512 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200513
Radek Krejci0d70c372015-07-02 16:23:10 +0200514 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200515 if (p_ != -1) {
516 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
517 type->info.bits.count = i + 1;
518 goto error;
519 }
520
Radek Krejci0d70c372015-07-02 16:23:10 +0200521 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200522 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200523
524 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200525 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100526 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200527 type->info.bits.count = i + 1;
528 goto error;
529 }
530 type->info.bits.bit[i].pos = (uint32_t)p_;
531
Radek Krejcie663e012016-08-01 17:12:34 +0200532 if (!dertype->der) { /* directly derived type from bits built-in type */
533 /* keep the highest enum value for automatic increment */
534 if (type->info.bits.bit[i].pos >= p) {
535 p = type->info.bits.bit[i].pos;
536 p++;
537 } else {
538 /* check that the value is unique */
539 for (j = 0; j < i; j++) {
540 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
541 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
542 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
543 type->info.bits.bit[j].name);
544 type->info.bits.count = i + 1;
545 goto error;
546 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200547 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200548 }
549 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200550
551 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
552 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200553 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100554 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200555 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200556 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200557 }
Radek Krejcie663e012016-08-01 17:12:34 +0200558
559 if (!dertype->der) { /* directly derived type from bits built-in type */
560 if (p_ == -1) {
561 /* assign value automatically */
562 if (p > UINT32_MAX) {
563 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
564 type->info.bits.count = i + 1;
565 goto error;
566 }
567 type->info.bits.bit[i].pos = (uint32_t)p;
568 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
569 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200570 }
Radek Krejcie663e012016-08-01 17:12:34 +0200571 } else { /* restricted bits type */
572 if (p_ == -1) {
573 /* automatically assign position from base type */
574 type->info.bits.bit[i].pos = bits_sc[j].pos;
575 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
576 } else {
577 /* check that the assigned position corresponds to the original
578 * position of the bit in the base type */
579 if (p_ != bits_sc[j].pos) {
580 /* p_ - assigned position in restricted bits
581 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
582 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200583 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200584 type->info.bits.count = i + 1;
585 goto error;
586 }
587 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200588 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200589
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200590 /* if-features */
591 if (c_ftrs) {
592 bits_sc = &type->info.bits.bit[i];
593 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
594 if (!bits_sc->iffeature) {
595 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200596 type->info.bits.count = i + 1;
597 goto error;
598 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200599
600 LY_TREE_FOR(next->child, node) {
601 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200602 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200603 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
604 bits_sc->iffeature_size++;
605 if (rc) {
606 type->info.bits.count = i + 1;
607 goto error;
608 }
609 }
610 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200611 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200612
613 /* keep them ordered by position */
614 j = i;
615 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
616 /* switch them */
617 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
618 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
619 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
620 j--;
621 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200622 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200625 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200626 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200627 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200628
Radek Krejcif9401c32015-06-26 16:47:36 +0200629 if (!strcmp(node->name, "range")) {
630 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100631 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200632 goto error;
633 }
634
635 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200636 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100637 if (!type->info.dec64.range) {
638 LOGMEM;
639 goto error;
640 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200641 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
642
643 /* get possible substatements */
644 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
645 goto error;
646 }
647 } else if (!strcmp(node->name, "fraction-digits")) {
648 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100649 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200650 goto error;
651 }
652 GETVAL(value, node, "value");
653 v = strtol(value, NULL, 10);
654
655 /* range check */
656 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100657 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200658 goto error;
659 }
660 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200661 type->info.dec64.div = 10;
662 for (i = 1; i < v; i++) {
663 type->info.dec64.div *= 10;
664 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200665 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100666 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200667 goto error;
668 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200669 }
670
671 /* mandatory sub-statement(s) check */
672 if (!type->info.dec64.dig && !type->der->type.der) {
673 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100674 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200675 goto error;
676 }
Radek Krejci7511f402015-07-10 09:56:30 +0200677 if (type->info.dec64.dig && type->der->type.der) {
678 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100679 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200680 goto error;
681 }
Radek Krejci4800f652016-09-08 14:02:52 +0200682
683 /* copy fraction-digits specification from parent type for easier internal use */
684 if (type->der->type.der) {
685 type->info.dec64.dig = type->der->type.info.dec64.dig;
686 type->info.dec64.div = type->der->type.info.dec64.div;
687 }
688
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200689 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
690 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
691 goto error;
692 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200693 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200695 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200696 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200697
Radek Krejci994b6f62015-06-18 16:47:27 +0200698 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200699 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200703 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200705 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200706 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200707 }
708 }
Radek Krejcie663e012016-08-01 17:12:34 +0200709 dertype = &type->der->type;
710 if (!dertype->der) {
711 if (!type->info.enums.count) {
712 /* type is derived directly from buit-in enumeartion type and enum statement is required */
713 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
714 goto error;
715 }
716 } else {
717 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
718 if (module->version < 2 && type->info.enums.count) {
719 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
720 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200722 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200723 goto error;
724 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200725 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200726
Radek Krejci1574a8d2015-08-03 14:16:52 +0200727 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100728 if (!type->info.enums.enm) {
729 LOGMEM;
730 goto error;
731 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200732
Radek Krejcie663e012016-08-01 17:12:34 +0200733 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200734 i = -1;
735 LY_TREE_FOR(yin->child, next) {
736 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200737 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200738
739 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100740 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100741 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
742 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100743 goto error;
744 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200745 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200746 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200747 type->info.enums.count = i + 1;
748 goto error;
749 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200751 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200752 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200753 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100754 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200755 type->info.enums.count = i + 1;
756 goto error;
757 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200758
Radek Krejcie663e012016-08-01 17:12:34 +0200759 if (!dertype->der) { /* directly derived type from enumeration built-in type */
760 /* check the name uniqueness */
761 for (j = 0; j < i; j++) {
762 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
763 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
764 type->info.enums.count = i + 1;
765 goto error;
766 }
767 }
768 } else {
769 /* restricted enumeration type - the name MUST be used in the base type */
770 enms_sc = dertype->info.enums.enm;
771 for (j = 0; j < dertype->info.enums.count; j++) {
772 if (ly_strequal(enms_sc[j].name, value, 1)) {
773 break;
774 }
775 }
776 if (j == dertype->info.enums.count) {
777 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200778 type->info.enums.count = i + 1;
779 goto error;
780 }
781 }
Radek Krejci04581c62015-05-22 21:24:00 +0200782
Radek Krejcie663e012016-08-01 17:12:34 +0200783 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200784 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200785 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
786 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200787 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200788 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789
Radek Krejci0d70c372015-07-02 16:23:10 +0200790 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200791 if (val_set) {
792 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
793 type->info.enums.count = i + 1;
794 goto error;
795 }
796
Radek Krejci0d70c372015-07-02 16:23:10 +0200797 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200798 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200799
800 /* range check */
801 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100802 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200803 type->info.enums.count = i + 1;
804 goto error;
805 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200806 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200807
Radek Krejcie663e012016-08-01 17:12:34 +0200808 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200809 if (!i) {
810 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200811 v = type->info.enums.enm[i].value;
812 v++;
813 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200814 /* keep the highest enum value for automatic increment */
815 if (type->info.enums.enm[i].value >= v) {
816 v = type->info.enums.enm[i].value;
817 v++;
818 } else {
819 /* check that the value is unique */
820 for (j = 0; j < i; j++) {
821 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
822 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
823 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
824 type->info.enums.enm[j].name);
825 type->info.enums.count = i + 1;
826 goto error;
827 }
Radek Krejcie663e012016-08-01 17:12:34 +0200828 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200829 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200830 }
831 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200832 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200833
834 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
835 c_ftrs++;
836
Radek Krejci0d70c372015-07-02 16:23:10 +0200837 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100838 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200839 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200840 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200841 }
Radek Krejcie663e012016-08-01 17:12:34 +0200842
843 if (!dertype->der) { /* directly derived type from enumeration */
844 if (!val_set) {
845 /* assign value automatically */
846 if (v > INT32_MAX) {
847 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
848 type->info.enums.count = i + 1;
849 goto error;
850 }
851 type->info.enums.enm[i].value = v;
852 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
853 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200854 }
Radek Krejcie663e012016-08-01 17:12:34 +0200855 } else { /* restricted enum type */
856 if (!val_set) {
857 /* automatically assign value from base type */
858 type->info.enums.enm[i].value = enms_sc[j].value;
859 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
860 } else {
861 /* check that the assigned value corresponds to the original
862 * value of the enum in the base type */
863 if (v_ != enms_sc[j].value) {
864 /* v_ - assigned value in restricted enum
865 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
866 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +0200867 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +0200868 type->info.enums.count = i + 1;
869 goto error;
870 }
871 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200872 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200873
874 /* if-features */
875 if (c_ftrs) {
876 enms_sc = &type->info.enums.enm[i];
877 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
878 if (!enms_sc->iffeature) {
879 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200880 type->info.enums.count = i + 1;
881 goto error;
882 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200883
884 LY_TREE_FOR(next->child, node) {
885 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200886 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200887 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
888 enms_sc->iffeature_size++;
889 if (rc) {
890 type->info.enums.count = i + 1;
891 goto error;
892 }
893 }
894 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 }
898 break;
899
900 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200901 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902
Michal Vaskof2d43962016-09-02 11:10:16 +0200903 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200904 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200905
Michal Vaskoe29c6622015-11-27 15:02:31 +0100906 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100907 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200908 goto error;
909 }
Michal Vaskof2d43962016-09-02 11:10:16 +0200910
911 GETVAL(value, yin->child, "name");
912 /* store in the JSON format */
913 value = transform_schema2json(module, value);
914 if (!value) {
915 goto error;
916 }
917 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
918 lydict_remove(module->ctx, value);
919
920 if (rc == -1) {
921 goto error;
922 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200923 }
924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200926 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +0200927 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +0200928 break;
929 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100930 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200931 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +0200932 } else {
933 if (type->der->type.der) {
934 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
935 goto error;
936 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100939 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 goto error;
941 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 break;
943
944 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200945 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200946 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200947
Radek Krejciaf351422015-06-19 14:49:38 +0200948 if (!strcmp(node->name, "require-instance")) {
949 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100950 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200951 goto error;
952 }
953 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200954 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200955 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200956 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200957 type->info.inst.req = -1;
958 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100959 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200960 goto error;
961 }
962 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100963 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200964 goto error;
965 }
Radek Krejciaf351422015-06-19 14:49:38 +0200966 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200968 break;
969
Radek Krejcif2860132015-06-20 12:37:20 +0200970 case LY_TYPE_BINARY:
971 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 case LY_TYPE_INT8:
973 case LY_TYPE_INT16:
974 case LY_TYPE_INT32:
975 case LY_TYPE_INT64:
976 case LY_TYPE_UINT8:
977 case LY_TYPE_UINT16:
978 case LY_TYPE_UINT32:
979 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200980 /* RFC 6020 9.2.4 - range */
981
982 /* length and range are actually the same restriction, so process
983 * them by this common code, we just need to differ the name and
984 * structure where the information will be stored
985 */
986 if (type->base == LY_TYPE_BINARY) {
987 restr = &type->info.binary.length;
988 name = "length";
989 } else {
990 restr = &type->info.num.range;
991 name = "range";
992 }
993
Radek Krejci73adb602015-07-02 18:07:40 +0200994 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200995
Radek Krejcif2860132015-06-20 12:37:20 +0200996 if (!strcmp(node->name, name)) {
997 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100998 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200999 goto error;
1000 }
1001
1002 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001003 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001004 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001005 goto error;
1006 }
1007 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +01001008 if (!(*restr)) {
1009 LOGMEM;
1010 goto error;
1011 }
Radek Krejcif2860132015-06-20 12:37:20 +02001012 (*restr)->expr = lydict_insert(module->ctx, value, 0);
1013
1014 /* get possible substatements */
1015 if (read_restr_substmt(module->ctx, *restr, node)) {
1016 goto error;
1017 }
1018 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001019 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001020 goto error;
1021 }
Radek Krejcif2860132015-06-20 12:37:20 +02001022 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001023 break;
1024
1025 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001026 /* flag resolving for later use */
1027 if (!tpdftype) {
1028 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1029 if (siter) {
1030 /* just a flag - do not resolve */
1031 tpdftype = 1;
1032 }
1033 }
1034
Radek Krejcidc4c1412015-06-19 15:39:54 +02001035 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001036 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001037
Michal Vasko88c29542015-11-27 14:57:53 +01001038 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001039 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001040 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001041 goto error;
1042 }
1043
1044 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001045 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001046 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001047 if (!type->info.lref.path) {
1048 goto error;
1049 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001050
1051 /* try to resolve leafref path only when this is instantiated
1052 * leaf, so it is not:
1053 * - typedef's type,
1054 * - in grouping definition,
1055 * - just instantiated in a grouping definition,
1056 * because in those cases the nodes referenced in path might not be present
1057 * and it is not a bug. */
1058 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001059 goto error;
1060 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001061 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001062 if (type->info.lref.req) {
1063 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1064 goto error;
1065 }
1066 GETVAL(value, node, "value");
1067 if (!strcmp(value, "true")) {
1068 type->info.lref.req = 1;
1069 } else if (!strcmp(value, "false")) {
1070 type->info.lref.req = -1;
1071 } else {
1072 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1073 goto error;
1074 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001075 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001076 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001077 goto error;
1078 }
Radek Krejci73adb602015-07-02 18:07:40 +02001079 }
1080
Radek Krejci742be352016-07-17 12:18:54 +02001081 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001082 if (!type->der->type.der) {
1083 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1084 goto error;
1085 } else {
1086 /* copy leafref definition into the derived type */
1087 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1088 /* and resolve the path at the place we are (if not in grouping/typedef) */
1089 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1090 goto error;
1091 }
1092
1093 /* add pointer to leafref target, only on leaves (not in typedefs) */
1094 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1095 goto error;
1096 }
1097 }
Radek Krejci742be352016-07-17 12:18:54 +02001098 }
1099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001100 break;
1101
1102 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001103 /* RFC 6020 9.4.4 - length */
1104 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001105 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001106 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001107
Radek Krejci3733a802015-06-19 13:43:21 +02001108 if (!strcmp(node->name, "length")) {
1109 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001110 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001111 goto error;
1112 }
1113
1114 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001115 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001116 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001117 goto error;
1118 }
1119 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001120 if (!type->info.str.length) {
1121 LOGMEM;
1122 goto error;
1123 }
Radek Krejci3733a802015-06-19 13:43:21 +02001124 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1125
Radek Krejci5fbc9162015-06-19 14:11:11 +02001126 /* get possible sub-statements */
1127 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001128 goto error;
1129 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001130 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001131 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001132 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001133 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001134 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001135 goto error;
1136 }
1137 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001138 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001139 if (i) {
1140 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001141 if (!type->info.str.patterns) {
1142 LOGMEM;
1143 goto error;
1144 }
Radek Krejci73adb602015-07-02 18:07:40 +02001145 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001146 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001147 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001148 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001149 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001150 goto error;
1151 }
Michal Vasko69068852015-07-13 14:34:31 +02001152
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001153 modifier = 0x06; /* ACK */
1154 name = NULL;
1155 LY_TREE_FOR_SAFE(node->child, next2, child) {
1156 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1157 /* garbage */
1158 lyxml_free(module->ctx, child);
1159 continue;
1160 }
1161
1162 if (module->version >= 2 && !strcmp(child->name, "modifier")) {
1163 if (name) {
1164 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1165 goto error;
1166 }
1167
1168 GETVAL(name, child, "value");
1169 if (!strcmp(name, "invert-match")) {
1170 modifier = 0x15; /* NACK */
1171 } else {
1172 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1173 goto error;
1174 }
1175 lyxml_free(module->ctx, child);
1176 }
1177 }
1178
1179 len = strlen(value);
1180 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1181 buf[0] = modifier;
1182 strcpy(&buf[1], value);
1183
1184 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001185
1186 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +01001187 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +02001188 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001189 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001190 goto error;
1191 }
Radek Krejci73adb602015-07-02 18:07:40 +02001192 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001193 }
1194 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 break;
1196
1197 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001198 /* RFC 6020 7.4 - type */
1199 /* count number of types in union */
1200 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001201 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001202
Radek Krejcie4c366b2015-07-02 10:11:31 +02001203 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001204 if (type->der->type.der) {
1205 /* type can be a substatement only in "union" type, not in derived types */
1206 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1207 goto error;
1208 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001209 i++;
1210 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001211 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001212 goto error;
1213 }
1214 }
1215
Radek Krejci038d5d92016-09-12 15:07:15 +02001216 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001217 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001218 goto error;
1219 }
1220
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001221 /* inherit instid presence information */
1222 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1223 type->info.uni.has_ptr_type = 1;
1224 }
1225
Radek Krejcie4c366b2015-07-02 10:11:31 +02001226 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001227 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001228 if (!type->info.uni.types) {
1229 LOGMEM;
1230 goto error;
1231 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001232 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001233 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001234 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001235 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001236 if (!rc) {
1237 type->info.uni.count++;
1238
Radek Krejci7de36cf2016-09-12 16:18:50 +02001239 if (module->version < 2) {
1240 /* union's type cannot be empty or leafref */
1241 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1242 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1243 rc = -1;
1244 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1245 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1246 rc = -1;
1247 }
Michal Vasko88c29542015-11-27 14:57:53 +01001248 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001249
1250 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1251 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1252 type->info.uni.has_ptr_type = 1;
1253 }
Michal Vasko88c29542015-11-27 14:57:53 +01001254 }
1255 if (rc) {
1256 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1257 for (i = 0; i < type->info.uni.count; ++i) {
1258 lys_type_free(module->ctx, &type->info.uni.types[i]);
1259 }
1260 free(type->info.uni.types);
1261 type->info.uni.types = NULL;
1262 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001263 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001264 type->der = NULL;
1265 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001266
1267 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001268 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001269 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001270 goto error;
1271 }
Michal Vasko88c29542015-11-27 14:57:53 +01001272 }
1273 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001274
Michal Vasko88c29542015-11-27 14:57:53 +01001275 case LY_TYPE_BOOL:
1276 case LY_TYPE_EMPTY:
1277 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001278 if (yin->child) {
1279 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
1280 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001281 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001282 break;
1283
1284 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001285 LOGINT;
1286 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001287 }
1288
1289 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001290
1291error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001292 if (type->module_name) {
1293 lydict_remove(module->ctx, type->module_name);
1294 type->module_name = NULL;
1295 }
Radek Krejcie534c132016-11-23 13:32:31 +01001296 lyxml_free_withsiblings(module->ctx, exts.child);
1297
Radek Krejcidc008d72016-02-17 13:12:14 +01001298 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001299}
1300
Michal Vasko0d343d12015-08-24 14:57:36 +02001301/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001303fill_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 +02001304{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001305 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001306 struct lyxml_elem *node, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001307 int rc, has_type = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001309 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001310 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001311 goto error;
1312 }
1313 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001315 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001316 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317 goto error;
1318 }
Radek Krejcieac35532015-05-31 19:09:15 +02001319
Michal Vasko88c29542015-11-27 14:57:53 +01001320 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001321 if (strcmp(node->ns->value, LY_NSYIN)) {
1322 /* extension */
1323 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001324 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001325 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001326 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001327 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001328 goto error;
1329 }
Michal Vasko88c29542015-11-27 14:57:53 +01001330 /* HACK for unres */
Radek Krejcie534c132016-11-23 13:32:31 +01001331 lyxml_unlink(module->ctx, node);
Michal Vasko88c29542015-11-27 14:57:53 +01001332 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001333 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001334 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001335 goto error;
1336 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001337 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001338
1339 /* skip lyxml_free() at the end of the loop */
1340 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001341 } else if (!strcmp(node->name, "default")) {
1342 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001343 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001344 goto error;
1345 }
1346 GETVAL(value, node, "value");
1347 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1348 } else if (!strcmp(node->name, "units")) {
1349 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001350 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001351 goto error;
1352 }
1353 GETVAL(value, node, "name");
1354 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1355 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001356 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001357 goto error;
1358 }
Radek Krejcie534c132016-11-23 13:32:31 +01001359
1360 lyxml_free(module->ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001361 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001363 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001364 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001365 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001366 goto error;
1367 }
Radek Krejcieac35532015-05-31 19:09:15 +02001368
Michal Vasko478c4652016-07-21 12:55:01 +02001369 /* check default value (if not defined, there still could be some restrictions
1370 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01001371 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 +02001372 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001373 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001374
Radek Krejcie534c132016-11-23 13:32:31 +01001375 /* finish extensions parsing */
1376 if (c_ext) {
1377 tpdf->ext = calloc(c_ext, sizeof *tpdf->ext);
1378 if (!tpdf->ext) {
1379 LOGMEM;
1380 goto error;
1381 }
1382 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0aa821a2016-12-08 11:21:35 +01001383 rc = fill_yin_ext(tpdf, LYEXT_PAR_TYPE, module, node, &tpdf->ext[tpdf->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001384 tpdf->ext_size++;
1385 if (rc) {
1386 goto error;
1387 }
1388 }
1389 }
1390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001391 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001392
1393error:
1394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001396}
1397
Radek Krejcia1a6b762016-11-14 09:53:38 +09001398static int
Radek Krejcie534c132016-11-23 13:32:31 +01001399fill_yin_extension(struct lys_module *module, struct lyxml_elem *yin, struct lys_ext *ext, struct unres_schema *unres)
Radek Krejcia1a6b762016-11-14 09:53:38 +09001400{
1401 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001402 struct lyxml_elem *child, *node, *next, *next2;
1403 int c_ext = 0, rc;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001404
1405 GETVAL(value, yin, "name");
1406
1407 if (lyp_check_identifier(value, LY_IDENT_EXTENSION, module, NULL)) {
1408 goto error;
1409 }
1410 ext->name = lydict_insert(module->ctx, value, strlen(value));
1411
1412 if (read_yin_common(module, NULL, (struct lys_node *)ext, yin, OPT_MODULE)) {
1413 goto error;
1414 }
1415
Radek Krejcie534c132016-11-23 13:32:31 +01001416 LY_TREE_FOR_SAFE(yin->child, next, node) {
1417 if (strcmp(node->ns->value, LY_NSYIN)) {
1418 /* possible extension instance */
1419 c_ext++;
1420 } else if (!strcmp(node->name, "argument")) {
1421 /* argument */
1422 GETVAL(value, node, "name");
1423 ext->argument = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001424
Radek Krejcia1a6b762016-11-14 09:53:38 +09001425 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001426 LY_TREE_FOR_SAFE(node->child, next2, child) {
1427 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
1428 GETVAL(value, child, "value");
1429 if (ly_strequal(value, "true", 0)) {
1430 ext->flags |= LYS_YINELEM;
1431 }
1432 } else if (child->ns) {
1433 /* unexpected YANG statement */
1434 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
1435 goto error;
1436 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001437 }
1438
Radek Krejcie534c132016-11-23 13:32:31 +01001439 lyxml_free(module->ctx, node);
1440 } else {
1441 /* unexpected YANG statement */
1442 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
1443 goto error;
1444 }
1445 }
1446
1447 if (c_ext) {
1448 ext->ext = calloc(c_ext, sizeof *ext->ext);
1449 if (!ext->ext) {
1450 LOGMEM;
1451 goto error;
1452 }
1453 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0aa821a2016-12-08 11:21:35 +01001454 rc = fill_yin_ext(ext, LYEXT_PAR_EXT, module, node, &ext->ext[ext->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001455 ext->ext_size++;
1456 if (rc) {
1457 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001458 }
1459 }
1460 }
1461
Radek Krejci0a498f82017-01-04 16:24:15 +01001462 /* search for plugin */
1463 ext->plugin = ext_get_plugin(ext->name, ext->module->name, ext->module->rev ? ext->module->rev[0].date : NULL);
Radek Krejcia1a6b762016-11-14 09:53:38 +09001464
1465 return EXIT_SUCCESS;
1466
1467error:
1468 return EXIT_FAILURE;
1469}
1470
Michal Vasko0d343d12015-08-24 14:57:36 +02001471/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001472static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001473fill_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 +02001474{
1475 const char *value;
1476 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001477 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001478
Radek Krejcib05774c2015-06-18 13:52:59 +02001479 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001480 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001481 goto error;
1482 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001483 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001484 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001485
Radek Krejci76512572015-08-04 09:47:08 +02001486 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001487 goto error;
1488 }
1489
Radek Krejcie534c132016-11-23 13:32:31 +01001490 LY_TREE_FOR(yin->child, child) {
1491 if (strcmp(child->ns->value, LY_NSYIN)) {
1492 /* extension */
1493 c_ext++;
1494 } else if (!strcmp(child->name, "if-feature")) {
1495 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001496 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001497 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001498 goto error;
1499 }
1500 }
1501
Radek Krejcie534c132016-11-23 13:32:31 +01001502 if (c_ftrs) {
1503 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001504 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001505 LOGMEM;
1506 goto error;
1507 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001508 }
Radek Krejcie534c132016-11-23 13:32:31 +01001509 if (c_ext) {
1510 f->ext = calloc(c_ext, sizeof *f->ext);
1511 if (!f->ext) {
1512 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001513 goto error;
1514 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001515 }
1516
Radek Krejcie534c132016-11-23 13:32:31 +01001517 LY_TREE_FOR_SAFE(yin->child, next, child) {
1518 if (strcmp(child->ns->value, LY_NSYIN)) {
1519 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01001520 ret = fill_yin_ext(f, LYEXT_PAR_FEATURE, module, child, &f->ext[f->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001521 f->ext_size++;
1522 if (ret) {
1523 goto error;
1524 }
1525 } else { /* if-feature */
1526 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1527 f->iffeature_size++;
1528 if (ret) {
1529 goto error;
1530 }
1531 }
1532 }
1533
Radek Krejcic79c6b12016-07-26 15:11:49 +02001534 /* check for circular dependencies */
1535 if (f->iffeature_size) {
1536 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1537 goto error;
1538 }
1539 }
1540
Radek Krejci3cf9e222015-06-18 11:37:50 +02001541 return EXIT_SUCCESS;
1542
1543error:
1544
1545 return EXIT_FAILURE;
1546}
1547
Michal Vasko0d343d12015-08-24 14:57:36 +02001548/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549static int
Radek Krejcib8048692015-08-05 13:36:34 +02001550fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001551{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001552 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001555 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001556 if (!must->expr) {
1557 goto error;
1558 }
Radek Krejci800af702015-06-02 13:46:01 +02001559
Radek Krejci41726f92015-06-19 13:11:05 +02001560 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001561
Michal Vasko77dc5652016-02-15 12:32:42 +01001562error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001563 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001564}
1565
Radek Krejci581ce772015-11-10 17:22:40 +01001566static int
Michal Vasko88c29542015-11-27 14:57:53 +01001567fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1568 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001569{
1570 int i, j;
1571 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001572 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001573
1574 /* get unique value (list of leafs supposed to be unique */
1575 GETVAL(value, yin, "tag");
1576
1577 /* count the number of unique leafs in the value */
1578 vaux = value;
1579 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001580 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001581 while (isspace(*vaux)) {
1582 vaux++;
1583 }
1584 }
1585 unique->expr_size++;
1586 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001587 if (!unique->expr) {
1588 LOGMEM;
1589 goto error;
1590 }
Radek Krejci581ce772015-11-10 17:22:40 +01001591
1592 for (i = 0; i < unique->expr_size; i++) {
1593 vaux = strpbrk(value, " \t\n");
1594 if (!vaux) {
1595 /* the last token, lydict_insert() will count its size on its own */
1596 vaux = value;
1597 }
1598
1599 /* store token into unique structure */
1600 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1601
1602 /* check that the expression does not repeat */
1603 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001604 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001605 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1606 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001607 goto error;
1608 }
1609 }
1610
1611 /* try to resolve leaf */
1612 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001613 unique_info = malloc(sizeof *unique_info);
1614 unique_info->list = parent;
1615 unique_info->expr = unique->expr[i];
1616 unique_info->trg_type = &unique->trg_type;
1617 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001618 goto error;
1619 }
Radek Krejci581ce772015-11-10 17:22:40 +01001620 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001621 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001622 goto error;
1623 }
1624 }
1625
1626 /* move to next token */
1627 value = vaux;
1628 while(isspace(*value)) {
1629 value++;
1630 }
1631 }
1632
1633 return EXIT_SUCCESS;
1634
1635error:
1636 return EXIT_FAILURE;
1637}
1638
Michal Vasko0d343d12015-08-24 14:57:36 +02001639/* logs directly
1640 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 * type: 0 - min, 1 - max
1642 */
1643static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001644deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001645{
1646 const char *value;
1647 char *endptr;
1648 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001649 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001650
Michal Vaskof7e57d52016-03-07 11:31:09 +01001651 /* del min/max is forbidden */
1652 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001653 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001654 goto error;
1655 }
1656
Radek Krejcieb00f512015-07-01 16:44:58 +02001657 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001658 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001659 max = &((struct lys_node_leaflist *)target)->max;
1660 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001661 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001662 max = &((struct lys_node_list *)target)->max;
1663 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001664 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001665 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1666 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 goto error;
1668 }
1669
1670 GETVAL(value, node, "value");
1671 while (isspace(value[0])) {
1672 value++;
1673 }
1674
Radek Krejci0d7b2472016-02-12 11:11:03 +01001675 if (type && !strcmp(value, "unbounded")) {
1676 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001677 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001678 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001679 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001680 /* convert it to uint32_t */
1681 errno = 0;
1682 endptr = NULL;
1683 val = strtoul(value, &endptr, 10);
1684 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001685 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001686 goto error;
1687 }
1688 if (type) {
1689 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001690 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001691 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001692 } else {
1693 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001694 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001695 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001696 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 }
1698
1699 if (d->mod == LY_DEVIATE_ADD) {
1700 /* check that there is no current value */
1701 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001702 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1703 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001704 goto error;
1705 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001706 } else if (d->mod == LY_DEVIATE_RPL) {
1707 /* unfortunately, there is no way to check reliably that there
1708 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001709 }
1710
Michal Vaskof7e57d52016-03-07 11:31:09 +01001711 /* add (already checked) and replace */
1712 /* set new value specified in deviation */
1713 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001714
Pavol Vican09adcc32016-08-25 10:51:36 +02001715 /* check min-elements is smaller than max-elements */
1716 if (*max && *min > *max) {
1717 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001718 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001719 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1720 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001721 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001722 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1723 }
1724 goto error;
1725 }
1726
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 return EXIT_SUCCESS;
1728
1729error:
1730
1731 return EXIT_FAILURE;
1732}
1733
Michal Vasko0d343d12015-08-24 14:57:36 +02001734/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001735static int
Michal Vasko88c29542015-11-27 14:57:53 +01001736fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1737 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001738{
1739 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01001740 struct lyxml_elem *next, *next2, *child, *develem;
1741 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001742 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001743 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001744 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001745 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001746 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001747 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001748 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001749 struct lys_node_leaf *leaf = NULL;
1750 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001751 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001752 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001753 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001754 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001755 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001756 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001757 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02001758
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001759 ctx = module->ctx;
1760
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001762 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001763 if (!dev->target_name) {
1764 goto error;
1765 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001766
1767 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001768 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01001769 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001770 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 goto error;
1772 }
Radek Krejcic4283442016-04-22 09:19:27 +02001773 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001774 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1775 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001776 goto error;
1777 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001778
1779 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01001780 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001781 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001782 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001783 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001784 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1785 /* extension */
1786 c_ext++;
1787 continue;
1788 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001789 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001790 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 goto error;
1792 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001793 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001794 if (!dev->dsc) {
1795 goto error;
1796 }
1797 } else if (!strcmp(child->name, "reference")) {
1798 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001799 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001800 goto error;
1801 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001802 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001803 if (!dev->ref) {
1804 goto error;
1805 }
1806 } else if (!strcmp(child->name, "deviate")) {
1807 c_dev++;
1808
Michal Vasko345da0a2015-12-02 10:35:55 +01001809 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001810 * further processed later
1811 */
1812 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001813
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001815 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 goto error;
1817 }
1818
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001819 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001820 }
1821
1822 if (c_dev) {
1823 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001824 if (!dev->deviate) {
1825 LOGMEM;
1826 goto error;
1827 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001828 } else {
1829 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1830 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001831 }
Radek Krejcie534c132016-11-23 13:32:31 +01001832 if (c_ext) {
1833 dev->ext = calloc(c_ext, sizeof *dev->ext);
1834 if (!dev->ext) {
1835 LOGMEM;
1836 goto error;
1837 }
1838 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001839
Radek Krejcie534c132016-11-23 13:32:31 +01001840
1841 LY_TREE_FOR_SAFE(yin->child, next, develem) {
1842 if (strcmp(develem->ns->value, LY_NSYIN)) {
1843 /* deviation's extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01001844 rc = fill_yin_ext(dev, LYEXT_PAR_DEVIATION, module, develem, &dev->ext[dev->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001845 dev->ext_size++;
1846 if (rc) {
1847 goto error;
1848 }
1849 continue;
1850 }
1851
1852 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02001853 /* init */
1854 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001855 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001856 c_must = 0;
1857 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001858 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01001859 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001860
1861 /* get deviation type */
1862 GETVAL(value, develem, "value");
1863 if (!strcmp(value, "not-supported")) {
1864 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1865 /* no property expected in this case */
1866 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001867 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001868 goto error;
1869 }
1870
Radek Krejci5b917642015-07-02 09:03:13 +02001871 /* and neither any other deviate statement is expected,
1872 * not-supported deviation must be the only deviation of the target
1873 */
1874 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001875 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1876 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001877 goto error;
1878 }
1879
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001880 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001881 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1882 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1883 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001884 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1885 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001886 goto error;
1887 }
1888 }
1889 }
Radek Krejci5b917642015-07-02 09:03:13 +02001890
Michal Vaskoff006c12016-02-17 11:15:19 +01001891 /* unlink and store the original node */
1892 lys_node_unlink(dev_target);
1893 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001894
Radek Krejci5b917642015-07-02 09:03:13 +02001895 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02001896 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02001897 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001898 } else if (!strcmp(value, "add")) {
1899 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1900 } else if (!strcmp(value, "replace")) {
1901 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1902 } else if (!strcmp(value, "delete")) {
1903 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1904 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001905 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001906 goto error;
1907 }
1908 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001909 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001910
Michal Vaskoff006c12016-02-17 11:15:19 +01001911 /* store a shallow copy of the original node */
1912 if (!dev->orig_node) {
1913 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01001914 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01001915 /* just to be safe */
1916 if (tmp_unres.count) {
1917 LOGINT;
1918 goto error;
1919 }
1920 }
1921
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01001923 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001924 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1925 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001926 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001927 continue;
1928 }
1929
Radek Krejcieb00f512015-07-01 16:44:58 +02001930 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001931 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001932 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001933 goto error;
1934 }
1935
1936 /* for we deviate from RFC 6020 and allow config property even it is/is not
1937 * specified in the target explicitly since config property inherits. So we expect
1938 * that config is specified in every node. But for delete, we check that the value
1939 * is the same as here in deviation
1940 */
1941 GETVAL(value, child, "value");
1942 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001943 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001944 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001945 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001946 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001947 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001948 goto error;
1949 }
1950
1951 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001952 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001953 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001954 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001955 } else { /* add and replace are the same in this case */
1956 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001957 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001958
1959 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001960 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001961 }
1962 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001963 c_dflt++;
1964
1965 /* check target node type */
1966 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1967 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1968 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1969 goto error;
1970 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1971 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1972 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1973 goto error;
1974 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
1975 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1976 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001977 goto error;
1978 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001979
Radek Krejcid5a5c282016-08-15 15:38:08 +02001980 /* skip lyxml_free() at the end of the loop, this node will be processed later */
1981 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02001982
Radek Krejcieb00f512015-07-01 16:44:58 +02001983 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001984 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001985 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001986 goto error;
1987 }
1988
1989 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001990 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001991 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1992 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001993 goto error;
1994 }
1995
1996 GETVAL(value, child, "value");
1997 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001998 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001999 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002000 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002001 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002002 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002003 goto error;
2004 }
2005
2006 if (d->mod == LY_DEVIATE_ADD) {
2007 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002008 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002009 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2010 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002011 goto error;
2012 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002013
Radek Krejci841ec082016-04-05 13:05:17 +02002014 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002015 if (d->flags & LYS_MAND_TRUE) {
2016 if (dev_target->nodetype == LYS_CHOICE) {
2017 if (((struct lys_node_choice *)(dev_target))->dflt) {
2018 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2019 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2020 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2021 goto error;
2022 }
2023 } else if (dev_target->nodetype == LYS_LEAF) {
2024 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2025 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2026 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2027 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2028 goto error;
2029 }
2030 }
Radek Krejci841ec082016-04-05 13:05:17 +02002031 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002032
Michal Vasko21be1b32016-03-07 12:31:34 +01002033 dev_target->flags |= d->flags & LYS_MAND_MASK;
2034 } else if (d->mod == LY_DEVIATE_RPL) {
2035 /* check that there was a value before */
2036 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002037 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2038 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002039 goto error;
2040 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002041
Michal Vasko21be1b32016-03-07 12:31:34 +01002042 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002043 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002044 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002045 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002046 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002047 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002048 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002049
2050 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2051 for (parent = dev_target->parent;
2052 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2053 parent = parent->parent) {
2054 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2055 /* stop also on presence containers */
2056 break;
2057 }
2058 }
2059 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2060 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2061 if (lyp_check_mandatory_choice(parent)) {
2062 goto error;
2063 }
2064 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002065 } else if (!strcmp(child->name, "min-elements")) {
2066 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002067 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002068 goto error;
2069 }
2070 f_min = 1;
2071
Michal Vasko60f4b452016-02-12 11:02:55 +01002072 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002073 goto error;
2074 }
2075 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002076 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002077 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002078 goto error;
2079 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002080 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002081
Michal Vasko60f4b452016-02-12 11:02:55 +01002082 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002083 goto error;
2084 }
2085 } else if (!strcmp(child->name, "must")) {
2086 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002087 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 continue;
2089 } else if (!strcmp(child->name, "type")) {
2090 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002091 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002092 goto error;
2093 }
2094
Michal Vaskof7e57d52016-03-07 11:31:09 +01002095 /* add, del type is forbidden */
2096 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002097 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002098 goto error;
2099 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002100 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002101 goto error;
2102 }
2103
Radek Krejcieb00f512015-07-01 16:44:58 +02002104 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002105 if (dev_target->nodetype == LYS_LEAF) {
2106 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002107 if (((struct lys_node_leaf *)dev_target)->dflt) {
2108 ly_set_add(dflt_check, dev_target, 0);
2109 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002110 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2111 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002112 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2113 ly_set_add(dflt_check, dev_target, 0);
2114 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002115 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002116 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2117 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002118 goto error;
2119 }
2120
Radek Krejcieb00f512015-07-01 16:44:58 +02002121 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002122 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002123 /* HACK for unres */
2124 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002125 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002126 goto error;
2127 }
2128 d->type = t;
2129 } else if (!strcmp(child->name, "unique")) {
2130 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002131 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002132 continue;
2133 } else if (!strcmp(child->name, "units")) {
2134 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002135 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002136 goto error;
2137 }
2138
2139 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002140 if (dev_target->nodetype == LYS_LEAFLIST) {
2141 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2142 } else if (dev_target->nodetype == LYS_LEAF) {
2143 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002144 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002145 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2146 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002147 goto error;
2148 }
2149
2150 /* get units value */
2151 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002152 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002153
2154 /* apply to target */
2155 if (d->mod == LY_DEVIATE_ADD) {
2156 /* check that there is no current value */
2157 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002158 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2159 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002160 goto error;
2161 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002162
Michal Vasko21be1b32016-03-07 12:31:34 +01002163 *stritem = lydict_insert(ctx, value, 0);
2164 } else if (d->mod == LY_DEVIATE_RPL) {
2165 /* check that there was a value before */
2166 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002167 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2168 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002169 goto error;
2170 }
2171
2172 lydict_remove(ctx, *stritem);
2173 *stritem = lydict_insert(ctx, value, 0);
2174 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002175 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002176 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002177 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2178 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002179 goto error;
2180 }
2181 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002182 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002183 }
2184 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002185 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002186 goto error;
2187 }
2188
Michal Vasko88c29542015-11-27 14:57:53 +01002189 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002190 }
2191
2192 if (c_must) {
2193 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002194 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002195 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002196 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2197 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002198 break;
Radek Krejci76512572015-08-04 09:47:08 +02002199 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002200 trg_must = &((struct lys_node_container *)dev_target)->must;
2201 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002202 break;
Radek Krejci76512572015-08-04 09:47:08 +02002203 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002204 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2205 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002206 break;
Radek Krejci76512572015-08-04 09:47:08 +02002207 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002208 trg_must = &((struct lys_node_list *)dev_target)->must;
2209 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002210 break;
Radek Krejci76512572015-08-04 09:47:08 +02002211 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002212 case LYS_ANYDATA:
2213 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2214 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002215 break;
2216 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002217 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2218 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002219 goto error;
2220 }
2221
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002222 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002223
Radek Krejcieb00f512015-07-01 16:44:58 +02002224 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002225 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002226 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002227 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002228 } else if (d->mod == LY_DEVIATE_ADD) {
2229 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002230 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002231 if (!d->must) {
2232 LOGMEM;
2233 goto error;
2234 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002236 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002237 d->must_size = c_must;
2238 } else { /* LY_DEVIATE_DEL */
2239 d->must = calloc(c_must, sizeof *d->must);
2240 }
Michal Vasko253035f2015-12-17 16:58:13 +01002241 if (!d->must) {
2242 LOGMEM;
2243 goto error;
2244 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002245 }
2246 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002247 /* replace unique is forbidden */
2248 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002249 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002250 goto error;
2251 }
2252
Radek Krejcieb00f512015-07-01 16:44:58 +02002253 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002254 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002255 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2256 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002257 goto error;
2258 }
2259
Michal Vasko60f4b452016-02-12 11:02:55 +01002260 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002261 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002262 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002263 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002264 list->unique = d->unique;
2265 d->unique = &list->unique[list->unique_size];
2266 d->unique_size = c_uniq;
2267 } else { /* LY_DEVIATE_DEL */
2268 d->unique = calloc(c_uniq, sizeof *d->unique);
2269 }
Michal Vasko253035f2015-12-17 16:58:13 +01002270 if (!d->unique) {
2271 LOGMEM;
2272 goto error;
2273 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002274 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002275 if (c_dflt) {
2276 if (d->mod == LY_DEVIATE_ADD) {
2277 /* check that there is no current value */
2278 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2279 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2280 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2281 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2282 goto error;
2283 }
2284
2285 /* check collision with mandatory/min-elements */
2286 if ((dev_target->flags & LYS_MAND_TRUE) ||
2287 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2288 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2289 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2290 "Adding the \"default\" statement is forbidden on %s statement.",
2291 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2292 goto error;
2293 }
2294 } else if (d->mod == LY_DEVIATE_RPL) {
2295 /* check that there was a value before */
2296 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2297 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2298 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2299 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2300 goto error;
2301 }
2302 }
2303
2304 if (dev_target->nodetype == LYS_LEAFLIST) {
2305 /* reallocate default list in the target */
2306 llist = (struct lys_node_leaflist *)dev_target;
2307 if (d->mod == LY_DEVIATE_ADD) {
2308 /* reallocate (enlarge) the unique array of the target */
2309 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2310 } else if (d->mod == LY_DEVIATE_RPL) {
2311 /* reallocate (replace) the unique array of the target */
2312 for (i = 0; i < llist->dflt_size; i++) {
2313 lydict_remove(llist->module->ctx, llist->dflt[i]);
2314 }
2315 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2316 llist->dflt_size = 0;
2317 }
2318 }
2319 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2320 if (!d->dflt) {
2321 LOGMEM;
2322 goto error;
2323 }
2324 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002325
2326 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002327 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002328 if (!strcmp(child->name, "must")) {
2329 if (d->mod == LY_DEVIATE_DEL) {
2330 if (fill_yin_must(module, child, &d->must[d->must_size])) {
2331 goto error;
2332 }
2333
2334 /* find must to delete, we are ok with just matching conditions */
2335 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002336 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002337 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002338 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002339 /* ... and maintain the array */
2340 (*trg_must_size)--;
2341 if (i != *trg_must_size) {
2342 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2343 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2344 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2345 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2346 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2347 }
2348 if (!(*trg_must_size)) {
2349 free(*trg_must);
2350 *trg_must = NULL;
2351 } else {
2352 (*trg_must)[*trg_must_size].expr = NULL;
2353 (*trg_must)[*trg_must_size].dsc = NULL;
2354 (*trg_must)[*trg_must_size].ref = NULL;
2355 (*trg_must)[*trg_must_size].eapptag = NULL;
2356 (*trg_must)[*trg_must_size].emsg = NULL;
2357 }
2358
2359 i = -1; /* set match flag */
2360 break;
2361 }
2362 }
2363 d->must_size++;
2364 if (i != -1) {
2365 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002366 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002367 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002368 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002369 goto error;
2370 }
2371 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002372 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2373 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002374 goto error;
2375 }
2376 (*trg_must_size)++;
2377 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002378
2379 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002380 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002381 goto error;
2382 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002383 } else if (!strcmp(child->name, "unique")) {
2384 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002385 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002386 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002387 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002388 goto error;
2389 }
2390
2391 /* find unique structures to delete */
2392 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002393 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002394 continue;
2395 }
2396
Radek Krejci581ce772015-11-10 17:22:40 +01002397 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002398 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002399 break;
2400 }
2401 }
2402
Radek Krejci581ce772015-11-10 17:22:40 +01002403 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002404 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002405 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002406 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002407 }
2408 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002409 /* ... and maintain the array */
2410 list->unique_size--;
2411 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002412 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2413 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002414 }
2415
2416 if (!list->unique_size) {
2417 free(list->unique);
2418 list->unique = NULL;
2419 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002420 list->unique[list->unique_size].expr_size = 0;
2421 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002422 }
2423
2424 i = -1; /* set match flag */
2425 break;
2426 }
2427 }
2428
2429 d->unique_size++;
2430 if (i != -1) {
2431 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002432 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2433 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002434 goto error;
2435 }
2436 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002437 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002438 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002439 list->unique_size++;
2440 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002441 goto error;
2442 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002443 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002444 } else if (!strcmp(child->name, "default")) {
2445 GETVAL(value, child, "value");
2446 u = strlen(value);
2447 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2448
2449 if (dev_target->nodetype == LYS_CHOICE) {
2450 choice = (struct lys_node_choice *)dev_target;
2451 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2452 if (rc || !node) {
2453 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2454 goto error;
2455 }
2456 if (d->mod == LY_DEVIATE_DEL) {
2457 if (!choice->dflt || (choice->dflt != node)) {
2458 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2459 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2460 goto error;
2461 }
2462 } else { /* add or replace */
2463 choice->dflt = node;
2464 if (!choice->dflt) {
2465 /* default branch not found */
2466 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2467 goto error;
2468 }
2469 }
2470 } else if (dev_target->nodetype == LYS_LEAF) {
2471 leaf = (struct lys_node_leaf *)dev_target;
2472 if (d->mod == LY_DEVIATE_DEL) {
2473 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2474 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2475 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2476 goto error;
2477 }
2478 /* remove value */
2479 lydict_remove(ctx, leaf->dflt);
2480 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002481 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002482 } else { /* add (already checked) and replace */
2483 /* remove value */
2484 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002485 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002486
2487 /* set new value */
2488 leaf->dflt = lydict_insert(ctx, value, u);
2489
Radek Krejcibd117f02016-11-04 16:28:08 +01002490 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002491 ly_set_add(dflt_check, dev_target, 0);
2492 }
2493 } else { /* LYS_LEAFLIST */
2494 llist = (struct lys_node_leaflist *)dev_target;
2495 if (d->mod == LY_DEVIATE_DEL) {
2496 /* find and remove the value in target list */
2497 for (i = 0; i < llist->dflt_size; i++) {
2498 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2499 /* match, remove the value */
2500 lydict_remove(llist->module->ctx, llist->dflt[i]);
2501 llist->dflt[i] = NULL;
2502 break;
2503 }
2504 }
2505 if (i == llist->dflt_size) {
2506 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2507 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2508 goto error;
2509 }
2510 } else {
2511 /* add or replace, anyway we place items into the deviate's list
2512 which propagates to the target */
2513 /* we just want to check that the value isn't already in the list */
2514 for (i = 0; i < llist->dflt_size; i++) {
2515 if (ly_strequal(llist->dflt[i], value, 1)) {
2516 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2517 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2518 goto error;
2519 }
2520 }
2521 /* store it in target node */
2522 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2523
2524 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2525 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01002526 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002527 }
2528 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002529 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002530 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002531
2532 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2533 /* consolidate the final list in the target after removing items from it */
2534 llist = (struct lys_node_leaflist *)dev_target;
2535 for (i = j = 0; j < llist->dflt_size; j++) {
2536 llist->dflt[i] = llist->dflt[j];
2537 if (llist->dflt[i]) {
2538 i++;
2539 }
2540 }
2541 llist->dflt_size = i + 1;
2542 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002543 }
2544
Michal Vasko43a1feb2016-03-07 12:03:02 +01002545 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002546 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002547 value = NULL;
2548 rc = EXIT_SUCCESS;
2549 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2550 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002551 value = leaf->dflt;
2552 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002553 } else { /* LYS_LEAFLIST */
2554 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2555 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002556 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2557 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002558 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002559 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002560 break;
2561 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002562 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002563
2564 }
2565 if (rc == -1) {
2566 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2568 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2569 dev->target_name);
2570 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002571 }
2572 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002573
Radek Krejci27fe55e2016-09-13 17:13:35 +02002574 /* mark all the affected modules as deviated and implemented */
2575 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2576 mod = lys_node_module(parent);
2577 if (module != mod) {
2578 mod->deviated = 1;
2579 lys_set_implemented(mod);
2580 }
2581 }
2582
Radek Krejcid5a5c282016-08-15 15:38:08 +02002583 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 return EXIT_SUCCESS;
2585
2586error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002587 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002588 return EXIT_FAILURE;
2589}
2590
Michal Vasko0d343d12015-08-24 14:57:36 +02002591/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002592static int
Radek Krejcib8048692015-08-05 13:36:34 +02002593fill_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 +02002594 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002595{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002596 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002597 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002598 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002599 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02002600
Michal Vasko591e0b22015-08-13 13:53:43 +02002601 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002603 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002604 if (!aug->target_name) {
2605 goto error;
2606 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002608
Radek Krejci6ff885d2017-01-03 14:06:22 +01002609 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002610 goto error;
2611 }
2612
Radek Krejcie534c132016-11-23 13:32:31 +01002613 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2614 if (strcmp(sub->ns->value, LY_NSYIN)) {
2615 /* extension */
2616 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002617 continue;
2618 }
2619
Radek Krejcie534c132016-11-23 13:32:31 +01002620 if (!strcmp(sub->name, "if-feature")) {
2621 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002622 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002623 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002624 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002625 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002626 goto error;
2627 }
2628
Radek Krejcie534c132016-11-23 13:32:31 +01002629 aug->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002630 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002631 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002632 goto error;
2633 }
Radek Krejcie534c132016-11-23 13:32:31 +01002634 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002635 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002636
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002637 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01002638 } else if (!strcmp(sub->name, "container")) {
2639 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
2640 } else if (!strcmp(sub->name, "leaf-list")) {
2641 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
2642 } else if (!strcmp(sub->name, "leaf")) {
2643 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
2644 } else if (!strcmp(sub->name, "list")) {
2645 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
2646 } else if (!strcmp(sub->name, "uses")) {
2647 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
2648 } else if (!strcmp(sub->name, "choice")) {
2649 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
2650 } else if (!strcmp(sub->name, "case")) {
2651 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
2652 } else if (!strcmp(sub->name, "anyxml")) {
2653 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
2654 } else if (!strcmp(sub->name, "anydata")) {
2655 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
2656 } else if (!strcmp(sub->name, "action")) {
2657 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
2658 } else if (!strcmp(sub->name, "notification")) {
2659 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002660 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01002661 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002662 goto error;
2663 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002664
Radek Krejci1d82ef62015-08-07 14:44:40 +02002665 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002666 goto error;
2667 }
2668
Radek Krejci1d82ef62015-08-07 14:44:40 +02002669 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002670 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002671 }
2672
Radek Krejcie534c132016-11-23 13:32:31 +01002673 if (c_ftrs) {
2674 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002675 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002676 LOGMEM;
2677 goto error;
2678 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002679 }
Radek Krejcie534c132016-11-23 13:32:31 +01002680 if (c_ext) {
2681 aug->ext = calloc(c_ext, sizeof *aug->ext);
2682 if (!aug->ext) {
2683 LOGMEM;
2684 goto error;
2685 }
2686 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002687
Radek Krejcie534c132016-11-23 13:32:31 +01002688 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2689 if (strcmp(sub->ns->value, LY_NSYIN)) {
2690 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01002691 ret = fill_yin_ext(aug, LYEXT_PAR_NODE, module, sub, &aug->ext[aug->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01002692 aug->ext_size++;
2693 if (ret) {
2694 goto error;
2695 }
2696 } else if (!strcmp(sub->name, "if-feature")) {
2697 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002698 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002699 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002700 goto error;
2701 }
Radek Krejcie534c132016-11-23 13:32:31 +01002702 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002703 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002704 }
2705
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002706 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002707 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002708 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002709 * when the uses does and cannot be resolved now for sure
2710 * (the grouping was not yet copied into uses).
2711 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002712 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002713 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002714 goto error;
2715 }
Michal Vasko49291b32015-08-06 09:49:41 +02002716 }
Radek Krejci106efc02015-06-10 14:36:27 +02002717
Michal Vasko508a50d2016-09-07 14:50:33 +02002718 /* check XPath dependencies */
2719 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2720 goto error;
2721 }
2722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002724
2725error:
2726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002728}
2729
Michal Vasko0d343d12015-08-24 14:57:36 +02002730/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002732fill_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 +02002733{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002734 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 struct lyxml_elem *sub, *next;
2736 const char *value;
2737 char *endptr;
2738 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002739 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 int r;
2741 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002742
Radek Krejci363bd4a2016-07-29 14:30:20 +02002743 assert(uses);
2744 module = uses->module; /* shorthand */
2745
Radek Krejcie534c132016-11-23 13:32:31 +01002746 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CFG_PARSE | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002747 goto error;
2748 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002749
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002750 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002751 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002752 if (!rfn->target_name) {
2753 goto error;
2754 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002756 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01002757 if (strcmp(sub->ns->value, LY_NSYIN)) {
2758 /* extension */
2759 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002760 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02002761
Radek Krejcie534c132016-11-23 13:32:31 +01002762 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002763 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 /* check possibility of statements combination */
2766 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002767 if (c_dflt) {
2768 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002769 if (module->version < 2) {
2770 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2771 goto error;
2772 }
Radek Krejci200bf712016-08-16 17:11:04 +02002773 rfn->target_type &= LYS_LEAFLIST;
2774 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002775 if (module->version < 2) {
2776 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2777 } else {
2778 /* YANG 1.1 */
2779 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2780 }
Radek Krejci200bf712016-08-16 17:11:04 +02002781 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002783 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2784 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 goto error;
2786 }
2787 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002788 if (module->version < 2) {
2789 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2790 } else {
2791 /* YANG 1.1 */
2792 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2793 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002794 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002795
Radek Krejci200bf712016-08-16 17:11:04 +02002796 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002797 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002798 } else if (!strcmp(sub->name, "mandatory")) {
2799 /* leaf, choice or anyxml */
2800 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002801 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 goto error;
2803 }
2804 /* just checking the flags in leaf is not sufficient, we would allow
2805 * multiple mandatory statements with the "false" value
2806 */
2807 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 /* check possibility of statements combination */
2810 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002811 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002813 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2814 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002815 goto error;
2816 }
2817 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002818 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 GETVAL(value, sub, "value");
2822 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002823 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002824 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002825 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002827 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002828 goto error;
2829 }
2830 } else if (!strcmp(sub->name, "min-elements")) {
2831 /* list or leaf-list */
2832 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002833 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834 goto error;
2835 }
2836 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 /* check possibility of statements combination */
2839 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002840 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002842 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2843 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 goto error;
2845 }
2846 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002847 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 GETVAL(value, sub, "value");
2851 while (isspace(value[0])) {
2852 value++;
2853 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 /* convert it to uint32_t */
2856 errno = 0;
2857 endptr = NULL;
2858 val = strtoul(value, &endptr, 10);
2859 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002860 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 goto error;
2862 }
2863 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002864 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002865 } else if (!strcmp(sub->name, "max-elements")) {
2866 /* list or leaf-list */
2867 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002868 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 goto error;
2870 }
2871 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002872
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002873 /* check possibility of statements combination */
2874 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002875 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002876 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002877 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2878 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002879 goto error;
2880 }
2881 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002882 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 GETVAL(value, sub, "value");
2886 while (isspace(value[0])) {
2887 value++;
2888 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002889
Radek Krejci0d7b2472016-02-12 11:11:03 +01002890 if (!strcmp(value, "unbounded")) {
2891 rfn->mod.list.max = 0;
2892 } else {
2893 /* convert it to uint32_t */
2894 errno = 0;
2895 endptr = NULL;
2896 val = strtoul(value, &endptr, 10);
2897 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002898 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002899 goto error;
2900 }
2901 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002903 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002904 } else if (!strcmp(sub->name, "presence")) {
2905 /* container */
2906 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002907 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908 goto error;
2909 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 /* check possibility of statements combination */
2912 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002913 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002915 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2916 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 goto error;
2918 }
2919 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002920 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 GETVAL(value, sub, "value");
2924 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2925 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002926 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 /* check possibility of statements combination */
2928 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002929 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002930 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002931 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2932 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 goto error;
2934 }
2935 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002936 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002939 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002940 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002941
Radek Krejci363bd4a2016-07-29 14:30:20 +02002942 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2943 /* leaf, leaf-list, list, container or anyxml */
2944 /* check possibility of statements combination */
2945 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002946 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002947 if (!rfn->target_type) {
2948 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2949 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2950 goto error;
2951 }
2952 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002953 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002954 }
2955
2956 c_ftrs++;
2957 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002959 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002960 goto error;
2961 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002962
Michal Vasko345da0a2015-12-02 10:35:55 +01002963 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 /* process nodes with cardinality of 0..n */
2967 if (c_must) {
2968 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002969 if (!rfn->must) {
2970 LOGMEM;
2971 goto error;
2972 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002974 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002975 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002976 if (!rfn->iffeature) {
2977 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002978 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 }
Radek Krejci200bf712016-08-16 17:11:04 +02002981 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002982 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002983 if (!rfn->dflt) {
2984 LOGMEM;
2985 goto error;
2986 }
2987 }
Radek Krejcie534c132016-11-23 13:32:31 +01002988 if (c_ext) {
2989 rfn->ext = calloc(c_ext, sizeof *rfn->ext);
2990 if (!rfn->ext) {
2991 LOGMEM;
2992 goto error;
2993 }
2994 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002995
Radek Krejcie534c132016-11-23 13:32:31 +01002996 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2997 if (strcmp(sub->ns->value, LY_NSYIN)) {
2998 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01002999 r = fill_yin_ext(rfn, LYEXT_PAR_REFINE, module, sub, &rfn->ext[rfn->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003000 rfn->ext_size++;
3001 if (r) {
3002 goto error;
3003 }
3004 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003005 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003006 rfn->iffeature_size++;
3007 if (r) {
3008 goto error;
3009 }
Radek Krejci200bf712016-08-16 17:11:04 +02003010 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003011 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
3012 rfn->must_size++;
3013 if (r) {
3014 goto error;
3015 }
Radek Krejci200bf712016-08-16 17:11:04 +02003016 } else { /* default */
3017 GETVAL(value, sub, "value");
3018
3019 /* check for duplicity */
3020 for (r = 0; r < rfn->dflt_size; r++) {
3021 if (ly_strequal(rfn->dflt[r], value, 1)) {
3022 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3023 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3024 goto error;
3025 }
3026 }
3027 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003028 }
3029 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003032
3033error:
3034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003036}
3037
Michal Vasko0d343d12015-08-24 14:57:36 +02003038/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039static int
Radek Krejcie534c132016-11-23 13:32:31 +01003040fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003041{
Radek Krejcie534c132016-11-23 13:32:31 +01003042 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003044 int r, c_ext = 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02003045
Radek Krejcie534c132016-11-23 13:32:31 +01003046 /* init */
3047 memset(&exts, 0, sizeof exts);
3048
3049 LY_TREE_FOR_SAFE(yin->child, next, child) {
3050 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003051 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003052 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003053 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3054 /* extension */
3055 c_ext++;
3056 lyxml_unlink_elem(module->ctx, child, 2);
3057 lyxml_add_child(module->ctx, &exts, child);
3058 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003060 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 goto error;
3062 }
3063 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
3064 } else if (!strcmp(child->name, "revision-date")) {
3065 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003066 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3067 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 }
3069 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003070 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 goto error;
3072 }
3073 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02003074 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003075 if (imp->dsc) {
3076 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3077 goto error;
3078 }
3079 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3080 if (!imp->dsc) {
3081 goto error;
3082 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003083 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003084 if (imp->ref) {
3085 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3086 goto error;
3087 }
3088 imp->ref = read_yin_subnode(module->ctx, child, "text");
3089 if (!imp->ref) {
3090 goto error;
3091 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003093 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 goto error;
3095 }
3096 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003098 /* check mandatory information */
3099 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003100 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 goto error;
3102 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003103
Radek Krejcie534c132016-11-23 13:32:31 +01003104 /* process extensions */
3105 if (c_ext) {
3106 imp->ext = calloc(c_ext, sizeof *imp->ext);
3107 if (!imp->ext) {
3108 LOGMEM;
3109 goto error;
3110 }
3111 LY_TREE_FOR_SAFE(exts.child, next, child) {
3112 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01003113 r = fill_yin_ext(imp, LYEXT_PAR_IMPORT, module, child, &imp->ext[imp->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003114 imp->ext_size++;
3115 if (r) {
3116 goto error;
3117 }
3118 }
3119 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003120
Radek Krejcie534c132016-11-23 13:32:31 +01003121 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003122 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003123
3124error:
3125
Radek Krejcie534c132016-11-23 13:32:31 +01003126 while (exts.child) {
3127 lyxml_free(module->ctx, exts.child);
3128 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003130}
3131
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003132/* logs directly
3133 * returns:
3134 * 0 - inc successfully filled
3135 * -1 - error, inc is cleaned
3136 * 1 - duplication, ignore the inc structure, inc is cleaned
3137 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003138static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003139fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3140 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003141{
Radek Krejcie534c132016-11-23 13:32:31 +01003142 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003143 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003144 int r, c_ext = 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02003145
Radek Krejcie534c132016-11-23 13:32:31 +01003146 /* init */
3147 memset(&exts, 0, sizeof exts);
3148
3149 LY_TREE_FOR_SAFE(yin->child, next, child) {
3150 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003151 /* garbage */
3152 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003153 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3154 /* extension */
3155 c_ext++;
3156 lyxml_unlink_elem(module->ctx, child, 2);
3157 lyxml_add_child(module->ctx, &exts, child);
3158 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003160 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003161 goto error;
3162 }
3163 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003164 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 goto error;
3166 }
3167 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02003168 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003169 if (inc->dsc) {
3170 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3171 goto error;
3172 }
3173 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3174 if (!inc->dsc) {
3175 goto error;
3176 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003177 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003178 if (inc->ref) {
3179 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3180 goto error;
3181 }
3182 inc->ref = read_yin_subnode(module->ctx, child, "text");
3183 if (!inc->ref) {
3184 goto error;
3185 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003187 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 goto error;
3189 }
3190 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003191
Radek Krejcie534c132016-11-23 13:32:31 +01003192 /* process extensions */
3193 if (c_ext) {
3194 inc->ext = calloc(c_ext, sizeof *inc->ext);
3195 if (!inc->ext) {
3196 LOGMEM;
3197 goto error;
3198 }
3199 LY_TREE_FOR_SAFE(exts.child, next, child) {
3200 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01003201 r = fill_yin_ext(inc, LYEXT_PAR_INCLUDE, module, child, &inc->ext[inc->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003202 inc->ext_size++;
3203 if (r) {
3204 goto error;
3205 }
3206 }
3207 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003208
Radek Krejcie534c132016-11-23 13:32:31 +01003209 GETVAL(value, yin, "module");
Pavol Vican0adf01d2016-03-22 12:29:33 +01003210 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003211
3212error:
3213
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003214 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003215}
3216
Michal Vasko0d343d12015-08-24 14:57:36 +02003217/* logs directly
3218 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003219 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003220 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003221 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003222 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223static int
Radek Krejcib8048692015-08-05 13:36:34 +02003224read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02003225 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003226{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003227 const char *value;
3228 struct lyxml_elem *sub, *next;
3229 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003232 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 if (opt & OPT_IDENT) {
3236 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003237 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 goto error;
3239 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003240 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 /* process local parameters */
3244 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003245 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003246 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003247 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003248 continue;
3249 }
3250 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003251 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003252 continue;
3253 }
3254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003256 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003257 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 goto error;
3259 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003260 node->dsc = read_yin_subnode(ctx, sub, "text");
3261 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003262 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 }
3264 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003265 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003266 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 goto error;
3268 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003269 node->ref = read_yin_subnode(ctx, sub, "text");
3270 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003271 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 }
3273 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003274 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003275 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003276 goto error;
3277 }
3278 GETVAL(value, sub, "value");
3279 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003280 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003282 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003284 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003286 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003287 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003289 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3290 if (opt & OPT_CFG_PARSE) {
3291 if (node->flags & LYS_CONFIG_MASK) {
3292 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3293 goto error;
3294 }
3295 GETVAL(value, sub, "value");
3296 if (!strcmp(value, "false")) {
3297 node->flags |= LYS_CONFIG_R;
3298 } else if (!strcmp(value, "true")) {
3299 node->flags |= LYS_CONFIG_W;
3300 } else {
3301 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3302 goto error;
3303 }
3304 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003307 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 continue;
3309 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003310 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003312
Michal Vaskoe022a562016-09-27 14:24:15 +02003313 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003315 if (parent) {
3316 node->flags |= parent->flags & LYS_CONFIG_MASK;
3317 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003319 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 }
3321 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003324
3325error:
3326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003328}
3329
Michal Vasko0d343d12015-08-24 14:57:36 +02003330/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003331static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003332read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003333{
Radek Krejci76512572015-08-04 09:47:08 +02003334 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003335 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003336 const char *value;
3337
3338 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003339 if (!retval) {
3340 LOGMEM;
3341 return NULL;
3342 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003343
3344 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003345 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003346 if (!retval->cond) {
3347 goto error;
3348 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003349
Radek Krejci73adb602015-07-02 18:07:40 +02003350 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003351 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3352 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003353 continue;
3354 }
3355
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003356 if (!strcmp(child->name, "description")) {
3357 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003358 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003359 goto error;
3360 }
3361 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3362 if (!retval->dsc) {
3363 goto error;
3364 }
3365 } else if (!strcmp(child->name, "reference")) {
3366 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003367 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003368 goto error;
3369 }
3370 retval->ref = read_yin_subnode(module->ctx, child, "text");
3371 if (!retval->ref) {
3372 goto error;
3373 }
3374 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003375 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003376 goto error;
3377 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003378 }
3379
3380 return retval;
3381
3382error:
3383
Michal Vasko0308dd62015-10-07 09:14:40 +02003384 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003385 return NULL;
3386}
3387
Michal Vasko0d343d12015-08-24 14:57:36 +02003388/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003389static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003390read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003391 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003392{
Michal Vasko29fc0182015-08-24 15:02:39 +02003393 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003394 struct lys_node_case *cs;
3395 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003396 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003397
Radek Krejcie867c852015-08-27 09:52:34 +02003398 /* init */
3399 memset(&root, 0, sizeof root);
3400
Radek Krejci1d82ef62015-08-07 14:44:40 +02003401 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003402 if (!cs) {
3403 LOGMEM;
3404 return NULL;
3405 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003406 cs->nodetype = LYS_CASE;
3407 cs->prev = (struct lys_node *)cs;
3408 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003409
Michal Vaskoe022a562016-09-27 14:24:15 +02003410 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01003411 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 goto error;
3413 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003414
Radek Krejcia9544502015-08-14 08:24:29 +02003415 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3416
Michal Vasko3a0043f2015-08-12 12:11:30 +02003417 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003418 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003419 goto error;
3420 }
3421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 /* process choice's specific children */
3423 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003424 if (strcmp(sub->ns->value, LY_NSYIN)) {
3425 /* extension */
3426 c_ext++;
3427 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003428 !strcmp(sub->name, "leaf-list") ||
3429 !strcmp(sub->name, "leaf") ||
3430 !strcmp(sub->name, "list") ||
3431 !strcmp(sub->name, "uses") ||
3432 !strcmp(sub->name, "choice") ||
3433 !strcmp(sub->name, "anyxml")) {
3434
Michal Vaskof3930de2015-10-22 12:03:59 +02003435 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003436 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003437 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003438 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003439 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003440 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003441 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003442 goto error;
3443 }
3444
Radek Krejci1d82ef62015-08-07 14:44:40 +02003445 cs->when = read_yin_when(module, sub);
3446 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003447 goto error;
3448 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003449
Michal Vasko345da0a2015-12-02 10:35:55 +01003450 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003452 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003456
Radek Krejci3cf9e222015-06-18 11:37:50 +02003457 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003458 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3459 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003460 LOGMEM;
3461 goto error;
3462 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003463 }
Radek Krejcie534c132016-11-23 13:32:31 +01003464 if (c_ext) {
3465 cs->ext = calloc(c_ext, sizeof *cs->ext);
3466 if (!cs->ext) {
3467 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003468 goto error;
3469 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003470 }
Radek Krejcie534c132016-11-23 13:32:31 +01003471 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3472 if (strcmp(sub->ns->value, LY_NSYIN)) {
3473 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01003474 ret = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003475 retval->ext_size++;
3476 if (ret) {
3477 goto error;
3478 }
3479 } else {
3480 /* if-feature */
3481 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3482 cs->iffeature_size++;
3483 if (ret) {
3484 goto error;
3485 }
3486 }
3487 }
Radek Krejcib388c152015-06-04 17:03:03 +02003488
Michal Vasko29fc0182015-08-24 15:02:39 +02003489 /* last part - process data nodes */
3490 LY_TREE_FOR_SAFE(root.child, next, sub) {
3491 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003492 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003493 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003494 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003495 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003496 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003497 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003498 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003499 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003500 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003501 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003502 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003503 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003504 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003505 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003506 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003507 }
3508 if (!node) {
3509 goto error;
3510 }
3511
Michal Vasko345da0a2015-12-02 10:35:55 +01003512 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003513 }
3514
Michal Vasko508a50d2016-09-07 14:50:33 +02003515 /* check XPath dependencies */
3516 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3517 goto error;
3518 }
3519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003521
3522error:
3523
Michal Vasko29fc0182015-08-24 15:02:39 +02003524 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003525 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003526 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003527 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003530}
3531
Michal Vasko0d343d12015-08-24 14:57:36 +02003532/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003533static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003534read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3535 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003536{
Radek Krejci629cdef2016-06-06 15:06:36 +02003537 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003539 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003540 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003541 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003542 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003545 if (!choice) {
3546 LOGMEM;
3547 return NULL;
3548 }
Radek Krejci76512572015-08-04 09:47:08 +02003549 choice->nodetype = LYS_CHOICE;
3550 choice->prev = (struct lys_node *)choice;
3551 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003552
Michal Vaskoe022a562016-09-27 14:24:15 +02003553 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01003554 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 goto error;
3556 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003557
Radek Krejcia9544502015-08-14 08:24:29 +02003558 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3559
Michal Vasko3a0043f2015-08-12 12:11:30 +02003560 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003561 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003562 goto error;
3563 }
3564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 /* process choice's specific children */
3566 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003567 if (strcmp(sub->ns->value, LY_NSYIN)) {
3568 /* extension */
3569 c_ext++;
3570 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003571 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003572 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003573 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 goto error;
3575 }
3576 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003577 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 goto error;
3579 }
3580 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003581 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 goto error;
3583 }
3584 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003585 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 goto error;
3587 }
3588 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003589 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 goto error;
3591 }
3592 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003593 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003594 goto error;
3595 }
3596 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003597 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003598 goto error;
3599 }
3600 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003601 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003602 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 goto error;
3604 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003605 dflt = sub;
3606 lyxml_unlink_elem(ctx, dflt, 0);
3607
Radek Krejcif9a312c2016-06-06 15:14:30 +02003608 continue;
3609 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003611 } else if (!strcmp(sub->name, "mandatory")) {
3612 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003613 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 goto error;
3615 }
3616 /* just checking the flags in leaf is not sufficient, we would allow
3617 * multiple mandatory statements with the "false" value
3618 */
3619 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 GETVAL(value, sub, "value");
3622 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003623 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003624 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003625 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003626 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003627 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 goto error;
3629 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003630 } else if (!strcmp(sub->name, "when")) {
3631 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003632 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003633 goto error;
3634 }
3635
3636 choice->when = read_yin_when(module, sub);
3637 if (!choice->when) {
3638 goto error;
3639 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003640 } else if (!strcmp(sub->name, "if-feature")) {
3641 c_ftrs++;
3642
Michal Vasko345da0a2015-12-02 10:35:55 +01003643 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003644 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003645 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003646 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02003647 goto error;
3648 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003650 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003653
Radek Krejci1d82ef62015-08-07 14:44:40 +02003654 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003655 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003657
Radek Krejci3cf9e222015-06-18 11:37:50 +02003658 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003659 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3660 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003661 LOGMEM;
3662 goto error;
3663 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003664 }
Radek Krejcie534c132016-11-23 13:32:31 +01003665 if (c_ext) {
3666 choice->ext = calloc(c_ext, sizeof *choice->ext);
3667 if (!choice->ext) {
3668 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003669 goto error;
3670 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003671 }
3672
Radek Krejcie534c132016-11-23 13:32:31 +01003673 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3674 if (strcmp(sub->ns->value, LY_NSYIN)) {
3675 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01003676 ret = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003677 retval->ext_size++;
3678 if (ret) {
3679 goto error;
3680 }
3681 } else {
3682 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
3683 choice->iffeature_size++;
3684 if (ret) {
3685 goto error;
3686 }
3687 }
3688 }
3689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003691 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003692 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
3693 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 goto error;
3695 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003698 if (dflt) {
3699 GETVAL(value, dflt, "value");
3700 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003701 goto error;
3702 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003703 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003705
Michal Vasko508a50d2016-09-07 14:50:33 +02003706 /* check XPath dependencies */
3707 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3708 goto error;
3709 }
3710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003712
3713error:
3714
Radek Krejci629cdef2016-06-06 15:06:36 +02003715 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003716 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003717
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003719}
3720
Michal Vasko0d343d12015-08-24 14:57:36 +02003721/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003722static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003723read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
3724 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003725{
Radek Krejci76512572015-08-04 09:47:08 +02003726 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003727 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 struct lyxml_elem *sub, *next;
3729 const char *value;
3730 int r;
3731 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003732 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003735 if (!anyxml) {
3736 LOGMEM;
3737 return NULL;
3738 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003739 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003740 anyxml->prev = (struct lys_node *)anyxml;
3741 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003742
Michal Vaskoe022a562016-09-27 14:24:15 +02003743 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01003744 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 goto error;
3746 }
Radek Krejci863c2852015-06-03 15:47:11 +02003747
Radek Krejcia9544502015-08-14 08:24:29 +02003748 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003749
Radek Krejcic189a952016-07-11 15:27:07 +02003750 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003751 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003752 goto error;
3753 }
3754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003756 if (strcmp(sub->ns->value, LY_NSYIN)) {
3757 /* extension */
3758 c_ext++;
3759 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003761 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 goto error;
3763 }
3764 /* just checking the flags in leaf is not sufficient, we would allow
3765 * multiple mandatory statements with the "false" value
3766 */
3767 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 GETVAL(value, sub, "value");
3770 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003771 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003772 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003773 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003774 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003775 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 goto error;
3777 }
3778 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003779 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003780 } else if (!strcmp(sub->name, "when")) {
3781 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003782 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003783 goto error;
3784 }
3785
3786 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003787 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003788 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003789 goto error;
3790 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003791 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 } else if (!strcmp(sub->name, "must")) {
3793 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003794 } else if (!strcmp(sub->name, "if-feature")) {
3795 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003798 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 }
3801 }
Radek Krejci863c2852015-06-03 15:47:11 +02003802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 /* middle part - process nodes with cardinality of 0..n */
3804 if (c_must) {
3805 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003806 if (!anyxml->must) {
3807 LOGMEM;
3808 goto error;
3809 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003811 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003812 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3813 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003814 LOGMEM;
3815 goto error;
3816 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003817 }
Radek Krejcie534c132016-11-23 13:32:31 +01003818 if (c_ext) {
3819 anyxml->ext = calloc(c_ext, sizeof *anyxml->ext);
3820 if (!anyxml->ext) {
3821 LOGMEM;
3822 goto error;
3823 }
3824 }
Radek Krejci863c2852015-06-03 15:47:11 +02003825
Radek Krejcie534c132016-11-23 13:32:31 +01003826 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3827 if (strcmp(sub->ns->value, LY_NSYIN)) {
3828 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01003829 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003830 retval->ext_size++;
3831 if (r) {
3832 goto error;
3833 }
3834 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003835 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3836 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 if (r) {
3838 goto error;
3839 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003840 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003841 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003842 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003843 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003844 goto error;
3845 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 }
Radek Krejci863c2852015-06-03 15:47:11 +02003848
Michal Vasko508a50d2016-09-07 14:50:33 +02003849 /* check XPath dependencies */
3850 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3851 goto error;
3852 }
3853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003855
3856error:
3857
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003858 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003860 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003861}
3862
Michal Vasko0d343d12015-08-24 14:57:36 +02003863/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003864static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003865read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003866 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003867{
Radek Krejci76512572015-08-04 09:47:08 +02003868 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003869 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 struct lyxml_elem *sub, *next;
3871 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003872 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003873 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003876 if (!leaf) {
3877 LOGMEM;
3878 return NULL;
3879 }
Radek Krejci76512572015-08-04 09:47:08 +02003880 leaf->nodetype = LYS_LEAF;
3881 leaf->prev = (struct lys_node *)leaf;
3882 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003883
Michal Vaskoe022a562016-09-27 14:24:15 +02003884 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01003885 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 goto error;
3887 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003888
Radek Krejcia9544502015-08-14 08:24:29 +02003889 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003890
Radek Krejcic189a952016-07-11 15:27:07 +02003891 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003892 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003893 goto error;
3894 }
3895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003897 if (strcmp(sub->ns->value, LY_NSYIN)) {
3898 /* extension */
3899 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003900 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003901 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003902 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003903 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 goto error;
3905 }
Michal Vasko88c29542015-11-27 14:57:53 +01003906 /* HACK for unres */
3907 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003908 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003909 /* postpone type resolution when if-feature parsing is done since we need
3910 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003911 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 } else if (!strcmp(sub->name, "default")) {
3913 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003914 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 goto error;
3916 }
3917 GETVAL(value, sub, "value");
3918 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3919 } else if (!strcmp(sub->name, "units")) {
3920 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003921 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 goto error;
3923 }
3924 GETVAL(value, sub, "name");
3925 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3926 } else if (!strcmp(sub->name, "mandatory")) {
3927 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003928 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 goto error;
3930 }
3931 /* just checking the flags in leaf is not sufficient, we would allow
3932 * multiple mandatory statements with the "false" value
3933 */
3934 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 GETVAL(value, sub, "value");
3937 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003938 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003939 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003940 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003941 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003942 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 goto error;
3944 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003945 } else if (!strcmp(sub->name, "when")) {
3946 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003947 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003948 goto error;
3949 }
3950
3951 leaf->when = read_yin_when(module, sub);
3952 if (!leaf->when) {
3953 goto error;
3954 }
3955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003956 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003957 c_must++;
3958 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003959 } else if (!strcmp(sub->name, "if-feature")) {
3960 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003964 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003967
Michal Vasko88c29542015-11-27 14:57:53 +01003968 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003969 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003972 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003973 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003974 goto error;
3975 }
Michal Vasko478c4652016-07-21 12:55:01 +02003976 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003977 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
3978 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval,
Michal Vasko478c4652016-07-21 12:55:01 +02003979 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3980 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003981 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003983 /* middle part - process nodes with cardinality of 0..n */
3984 if (c_must) {
3985 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003986 if (!leaf->must) {
3987 LOGMEM;
3988 goto error;
3989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003990 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003991 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003992 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3993 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003994 LOGMEM;
3995 goto error;
3996 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003997 }
Radek Krejcie534c132016-11-23 13:32:31 +01003998 if (c_ext) {
3999 leaf->ext = calloc(c_ext, sizeof *leaf->ext);
4000 if (!leaf->ext) {
4001 LOGMEM;
4002 goto error;
4003 }
4004 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004005
Radek Krejcie534c132016-11-23 13:32:31 +01004006 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4007 if (strcmp(sub->ns->value, LY_NSYIN)) {
4008 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01004009 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004010 retval->ext_size++;
4011 if (r) {
4012 goto error;
4013 }
4014 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004015 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
4016 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 if (r) {
4018 goto error;
4019 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004020 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004021 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004022 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004023 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004024 goto error;
4025 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004028
Radek Krejcicbb473e2016-09-16 14:48:32 +02004029 /* finalize type parsing */
4030 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4031 leaf->type.der = NULL;
4032 goto error;
4033 }
4034
4035 /* check default value (if not defined, there still could be some restrictions
4036 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004037 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 +02004038 goto error;
4039 }
4040
Michal Vasko508a50d2016-09-07 14:50:33 +02004041 /* check XPath dependencies */
4042 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4043 goto error;
4044 }
4045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004046 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004047
4048error:
4049
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004050 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004052 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004053}
4054
Michal Vasko0d343d12015-08-24 14:57:36 +02004055/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004056static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004057read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004058 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004059{
Radek Krejci76512572015-08-04 09:47:08 +02004060 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004061 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 struct lyxml_elem *sub, *next;
4063 const char *value;
4064 char *endptr;
4065 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004066 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004067 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004068 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004070 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004071 if (!llist) {
4072 LOGMEM;
4073 return NULL;
4074 }
Radek Krejci76512572015-08-04 09:47:08 +02004075 llist->nodetype = LYS_LEAFLIST;
4076 llist->prev = (struct lys_node *)llist;
4077 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004078
Michal Vaskoe022a562016-09-27 14:24:15 +02004079 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01004080 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004081 goto error;
4082 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004083
Radek Krejcia9544502015-08-14 08:24:29 +02004084 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004085
Radek Krejcic189a952016-07-11 15:27:07 +02004086 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004087 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004088 goto error;
4089 }
4090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004092 if (strcmp(sub->ns->value, LY_NSYIN)) {
4093 /* extension */
4094 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004095 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004096 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004097 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004098 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004099 goto error;
4100 }
Michal Vasko88c29542015-11-27 14:57:53 +01004101 /* HACK for unres */
4102 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004103 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004104 /* postpone type resolution when if-feature parsing is done since we need
4105 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004106 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004107 } else if (!strcmp(sub->name, "units")) {
4108 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004109 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004110 goto error;
4111 }
4112 GETVAL(value, sub, "name");
4113 llist->units = lydict_insert(module->ctx, value, strlen(value));
4114 } else if (!strcmp(sub->name, "ordered-by")) {
4115 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004116 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004117 goto error;
4118 }
4119 /* just checking the flags in llist is not sufficient, we would
4120 * allow multiple ordered-by statements with the "system" value
4121 */
4122 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004123
Radek Krejci1574a8d2015-08-03 14:16:52 +02004124 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004125 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4126 * state data
4127 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004128 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004129 continue;
4130 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004132 GETVAL(value, sub, "value");
4133 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004134 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004136 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004137 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004138 } /* else system is the default value, so we can ignore it */
4139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004140 } else if (!strcmp(sub->name, "must")) {
4141 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004142 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004143 } else if (!strcmp(sub->name, "if-feature")) {
4144 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004146 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
4147 c_dflt++;
4148 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004150 } else if (!strcmp(sub->name, "min-elements")) {
4151 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004152 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004153 goto error;
4154 }
4155 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 GETVAL(value, sub, "value");
4158 while (isspace(value[0])) {
4159 value++;
4160 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004162 /* convert it to uint32_t */
4163 errno = 0;
4164 endptr = NULL;
4165 val = strtoul(value, &endptr, 10);
4166 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004167 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 goto error;
4169 }
4170 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004171 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004172 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4173 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004174 goto error;
4175 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004176 } else if (!strcmp(sub->name, "max-elements")) {
4177 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004178 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004179 goto error;
4180 }
4181 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183 GETVAL(value, sub, "value");
4184 while (isspace(value[0])) {
4185 value++;
4186 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004187
Radek Krejci0d7b2472016-02-12 11:11:03 +01004188 if (!strcmp(value, "unbounded")) {
4189 llist->max = 0;
4190 } else {
4191 /* convert it to uint32_t */
4192 errno = 0;
4193 endptr = NULL;
4194 val = strtoul(value, &endptr, 10);
4195 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004196 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004197 goto error;
4198 }
4199 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004200 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004201 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4202 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004203 goto error;
4204 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004205 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004206 } else if (!strcmp(sub->name, "when")) {
4207 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004208 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004209 goto error;
4210 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004211
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004212 llist->when = read_yin_when(module, sub);
4213 if (!llist->when) {
4214 goto error;
4215 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004216 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004217 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004218 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004219 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004220
Michal Vasko88c29542015-11-27 14:57:53 +01004221 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004222 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004224 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004225 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004226 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004227 goto error;
4228 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 /* middle part - process nodes with cardinality of 0..n */
4231 if (c_must) {
4232 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004233 if (!llist->must) {
4234 LOGMEM;
4235 goto error;
4236 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004238 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004239 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4240 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004241 LOGMEM;
4242 goto error;
4243 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004244 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004245 if (c_dflt) {
4246 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4247 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004248 LOGMEM;
4249 goto error;
4250 }
4251 }
Radek Krejcie534c132016-11-23 13:32:31 +01004252 if (c_ext) {
4253 llist->ext = calloc(c_ext, sizeof *llist->ext);
4254 if (!llist->ext) {
4255 LOGMEM;
4256 goto error;
4257 }
4258 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004259
Radek Krejcie534c132016-11-23 13:32:31 +01004260 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4261 if (strcmp(sub->ns->value, LY_NSYIN)) {
4262 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01004263 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004264 retval->ext_size++;
4265 if (r) {
4266 goto error;
4267 }
4268 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004269 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
4270 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 if (r) {
4272 goto error;
4273 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004274 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004275 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004276 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004277 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004278 goto error;
4279 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004280 } else if (!strcmp(sub->name, "default")) {
4281 GETVAL(value, sub, "value");
4282
Radek Krejciac1a52c2016-09-15 14:42:40 +02004283 /* check for duplicity in case of configuration data,
4284 * in case of status data duplicities are allowed */
4285 if (llist->flags & LYS_CONFIG_W) {
4286 for (r = 0; r < llist->dflt_size; r++) {
4287 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004288 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
4289 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004290 goto error;
4291 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004292 }
4293 }
4294 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004297
Radek Krejcicbb473e2016-09-16 14:48:32 +02004298 /* finalize type parsing */
4299 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4300 llist->type.der = NULL;
4301 goto error;
4302 }
4303
Radek Krejcid5a5c282016-08-15 15:38:08 +02004304 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004305 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
4306 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004307 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4308 goto error;
4309 }
4310
4311 /* check default value (if not defined, there still could be some restrictions
4312 * that need to be checked against a default value from a derived type) */
4313 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004314 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4315 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004316 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004317 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004318 }
4319
Michal Vasko508a50d2016-09-07 14:50:33 +02004320 /* check XPath dependencies */
4321 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4322 goto error;
4323 }
4324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004326
4327error:
4328
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004329 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004332}
4333
Michal Vasko0d343d12015-08-24 14:57:36 +02004334/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004335static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004336read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004337 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004338{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004339 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004340 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004342 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004343 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004345 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004346 char *auxs;
4347 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004349 /* init */
4350 memset(&root, 0, sizeof root);
4351 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004353 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004354 if (!list) {
4355 LOGMEM;
4356 return NULL;
4357 }
Radek Krejci76512572015-08-04 09:47:08 +02004358 list->nodetype = LYS_LIST;
4359 list->prev = (struct lys_node *)list;
4360 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004361
Michal Vaskoe022a562016-09-27 14:24:15 +02004362 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01004363 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 goto error;
4365 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004366
Radek Krejcia9544502015-08-14 08:24:29 +02004367 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4368
Radek Krejcic189a952016-07-11 15:27:07 +02004369 /* insert the node into the schema tree */
4370 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4371 goto error;
4372 }
4373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 /* process list's specific children */
4375 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004376 if (strcmp(sub->ns->value, LY_NSYIN)) {
4377 /* extension */
4378 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004379 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004381 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004382 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004383 !strcmp(sub->name, "leaf-list") ||
4384 !strcmp(sub->name, "leaf") ||
4385 !strcmp(sub->name, "list") ||
4386 !strcmp(sub->name, "choice") ||
4387 !strcmp(sub->name, "uses") ||
4388 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004389 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004390 !strcmp(sub->name, "action") ||
4391 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004392 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004393 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 /* array counters */
4396 } else if (!strcmp(sub->name, "key")) {
4397 /* check cardinality 0..1 */
4398 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004399 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 goto error;
4401 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 /* count the number of keys */
4404 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004405 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004406 while ((value = strpbrk(value, " \t\n"))) {
4407 list->keys_size++;
4408 while (isspace(*value)) {
4409 value++;
4410 }
4411 }
4412 list->keys_size++;
4413 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004414 if (!list->keys) {
4415 LOGMEM;
4416 goto error;
4417 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 } else if (!strcmp(sub->name, "unique")) {
4419 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004420 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004421 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 } else if (!strcmp(sub->name, "typedef")) {
4423 c_tpdf++;
4424 } else if (!strcmp(sub->name, "must")) {
4425 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004426 } else if (!strcmp(sub->name, "if-feature")) {
4427 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 /* optional stetments */
4430 } else if (!strcmp(sub->name, "ordered-by")) {
4431 if (f_ordr) {
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 /* just checking the flags in llist is not sufficient, we would
4436 * allow multiple ordered-by statements with the "system" value
4437 */
4438 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004439
Radek Krejci1574a8d2015-08-03 14:16:52 +02004440 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4442 * state data
4443 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004444 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 continue;
4446 }
Radek Krejci345ad742015-06-03 11:04:18 +02004447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 GETVAL(value, sub, "value");
4449 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004450 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004451 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004452 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 goto error;
4454 }
4455 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004456 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004457 } else if (!strcmp(sub->name, "min-elements")) {
4458 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004459 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 goto error;
4461 }
4462 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 GETVAL(value, sub, "value");
4465 while (isspace(value[0])) {
4466 value++;
4467 }
Radek Krejci345ad742015-06-03 11:04:18 +02004468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 /* convert it to uint32_t */
4470 errno = 0;
4471 auxs = NULL;
4472 val = strtoul(value, &auxs, 10);
4473 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004474 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004475 goto error;
4476 }
4477 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004478 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004479 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4480 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004481 lyxml_free(module->ctx, sub);
4482 goto error;
4483 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004484 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 } else if (!strcmp(sub->name, "max-elements")) {
4486 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004487 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 goto error;
4489 }
4490 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 GETVAL(value, sub, "value");
4493 while (isspace(value[0])) {
4494 value++;
4495 }
Radek Krejci345ad742015-06-03 11:04:18 +02004496
Radek Krejci0d7b2472016-02-12 11:11:03 +01004497 if (!strcmp(value, "unbounded")) {
4498 list->max = 0;;
4499 } else {
4500 /* convert it to uint32_t */
4501 errno = 0;
4502 auxs = NULL;
4503 val = strtoul(value, &auxs, 10);
4504 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004505 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004506 goto error;
4507 }
4508 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004509 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004510 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4511 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004512 goto error;
4513 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004515 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004516 } else if (!strcmp(sub->name, "when")) {
4517 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004518 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004519 goto error;
4520 }
4521
4522 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004523 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004524 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004525 goto error;
4526 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004527 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004528 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004529 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004530 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 }
4532 }
Radek Krejci345ad742015-06-03 11:04:18 +02004533
Michal Vaskoe022a562016-09-27 14:24:15 +02004534 /* check - if list is configuration, key statement is mandatory
4535 * (but only if we are not in a grouping or augment, then the check is deferred) */
4536 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01004537 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004538 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004539 goto error;
4540 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4543 if (c_tpdf) {
4544 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004545 if (!list->tpdf) {
4546 LOGMEM;
4547 goto error;
4548 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004550 if (c_must) {
4551 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004552 if (!list->must) {
4553 LOGMEM;
4554 goto error;
4555 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004556 }
4557 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004558 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4559 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004560 LOGMEM;
4561 goto error;
4562 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004563 }
Radek Krejcie534c132016-11-23 13:32:31 +01004564 if (c_ext) {
4565 list->ext = calloc(c_ext, sizeof *list->ext);
4566 if (!list->ext) {
4567 LOGMEM;
4568 goto error;
4569 }
4570 }
4571 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4572 if (strcmp(sub->ns->value, LY_NSYIN)) {
4573 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01004574 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004575 retval->ext_size++;
4576 if (r) {
4577 goto error;
4578 }
4579 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004580 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4581 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 if (r) {
4583 goto error;
4584 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004585 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004586 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004587 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004588 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004589 goto error;
4590 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004591 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004592 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4593 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004594 if (r) {
4595 goto error;
4596 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 }
4598 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 /* last part - process data nodes */
4601 LY_TREE_FOR_SAFE(root.child, next, sub) {
4602 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004603 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004604 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004605 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004607 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004608 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004609 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004611 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004613 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004615 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004616 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004617 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004618 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004619 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004620 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004621 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004622 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004623 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004624 } else {
4625 LOGINT;
4626 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004627 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004628 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 goto error;
4630 }
Radek Krejci73adb602015-07-02 18:07:40 +02004631
Michal Vasko345da0a2015-12-02 10:35:55 +01004632 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004634
Radek Krejci5c08a992016-11-02 13:30:04 +01004635 if (list->keys_str) {
4636 /* check that we are not in grouping */
4637 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
4638 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004639 goto error;
4640 }
4641 } /* 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 +02004642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 /* process unique statements */
4644 if (c_uniq) {
4645 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004646 if (!list->unique) {
4647 LOGMEM;
4648 goto error;
4649 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004650
Radek Krejci461efb92016-02-12 15:52:18 +01004651 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4652 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4653 list->unique_size++;
4654 if (r) {
4655 goto error;
4656 }
4657
4658 lyxml_free(module->ctx, sub);
4659 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004660 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004661
Michal Vasko508a50d2016-09-07 14:50:33 +02004662 /* check XPath dependencies */
4663 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4664 goto error;
4665 }
4666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004668
4669error:
4670
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004671 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004673 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 }
4675 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004676 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004680}
4681
Michal Vasko0d343d12015-08-24 14:57:36 +02004682/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004683static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004684read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004685 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004686{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004687 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004688 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004689 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004690 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 const char *value;
4692 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004693 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 /* init */
4696 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004699 if (!cont) {
4700 LOGMEM;
4701 return NULL;
4702 }
Radek Krejci76512572015-08-04 09:47:08 +02004703 cont->nodetype = LYS_CONTAINER;
4704 cont->prev = (struct lys_node *)cont;
4705 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004706
Michal Vaskoe022a562016-09-27 14:24:15 +02004707 if (read_yin_common(module, parent, retval, yin,
Radek Krejci6ff885d2017-01-03 14:06:22 +01004708 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 goto error;
4710 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004711
Radek Krejcia9544502015-08-14 08:24:29 +02004712 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4713
Radek Krejcic189a952016-07-11 15:27:07 +02004714 /* insert the node into the schema tree */
4715 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4716 goto error;
4717 }
4718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 /* process container's specific children */
4720 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004721 if (strcmp(sub->ns->value, LY_NSYIN)) {
4722 /* extension */
4723 c_ext++;
4724 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004725 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004726 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
4729 GETVAL(value, sub, "value");
4730 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004731
Michal Vasko345da0a2015-12-02 10:35:55 +01004732 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004733 } else if (!strcmp(sub->name, "when")) {
4734 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004735 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004736 goto error;
4737 }
4738
4739 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004740 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004741 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004742 goto error;
4743 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004744 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 /* data statements */
4747 } else if (!strcmp(sub->name, "container") ||
4748 !strcmp(sub->name, "leaf-list") ||
4749 !strcmp(sub->name, "leaf") ||
4750 !strcmp(sub->name, "list") ||
4751 !strcmp(sub->name, "choice") ||
4752 !strcmp(sub->name, "uses") ||
4753 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004754 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004755 !strcmp(sub->name, "action") ||
4756 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004757 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004758 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004760 /* array counters */
4761 } else if (!strcmp(sub->name, "typedef")) {
4762 c_tpdf++;
4763 } else if (!strcmp(sub->name, "must")) {
4764 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004765 } else if (!strcmp(sub->name, "if-feature")) {
4766 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004768 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004769 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 }
4771 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004773 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4774 if (c_tpdf) {
4775 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004776 if (!cont->tpdf) {
4777 LOGMEM;
4778 goto error;
4779 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 }
4781 if (c_must) {
4782 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004783 if (!cont->must) {
4784 LOGMEM;
4785 goto error;
4786 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004788 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004789 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4790 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004791 LOGMEM;
4792 goto error;
4793 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004794 }
Radek Krejcie534c132016-11-23 13:32:31 +01004795 if (c_ext) {
4796 cont->ext = calloc(c_ext, sizeof *cont->ext);
4797 if (!cont->ext) {
4798 LOGMEM;
4799 goto error;
4800 }
4801 }
Radek Krejci800af702015-06-02 13:46:01 +02004802
Radek Krejcie534c132016-11-23 13:32:31 +01004803 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4804 if (strcmp(sub->ns->value, LY_NSYIN)) {
4805 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01004806 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004807 retval->ext_size++;
4808 if (r) {
4809 goto error;
4810 }
4811 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004812 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4813 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814 if (r) {
4815 goto error;
4816 }
4817 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004818 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4819 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004820 if (r) {
4821 goto error;
4822 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004823 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004824 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004825 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004826 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004827 goto error;
4828 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004829 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004832 /* last part - process data nodes */
4833 LY_TREE_FOR_SAFE(root.child, next, sub) {
4834 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004835 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004837 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004839 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004840 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004841 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004843 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004845 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004846 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004847 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004848 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004849 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004850 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004851 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004852 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004853 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004854 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004855 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004856 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004857 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004858 goto error;
4859 }
Radek Krejci73adb602015-07-02 18:07:40 +02004860
Michal Vasko345da0a2015-12-02 10:35:55 +01004861 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004862 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004863
Michal Vasko508a50d2016-09-07 14:50:33 +02004864 /* check XPath dependencies */
4865 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4866 goto error;
4867 }
4868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004870
4871error:
4872
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004873 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004875 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004879}
4880
Michal Vasko0d343d12015-08-24 14:57:36 +02004881/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004882static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004883read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004884 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004885{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004886 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004887 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004888 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004889 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004891 int c_tpdf = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004893 /* init */
4894 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004897 if (!grp) {
4898 LOGMEM;
4899 return NULL;
4900 }
Radek Krejci76512572015-08-04 09:47:08 +02004901 grp->nodetype = LYS_GROUPING;
4902 grp->prev = (struct lys_node *)grp;
4903 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004904
Radek Krejci5c08a992016-11-02 13:30:04 +01004905 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE )) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 goto error;
4907 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004908
Radek Krejcia9544502015-08-14 08:24:29 +02004909 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4910
Radek Krejcic189a952016-07-11 15:27:07 +02004911 /* insert the node into the schema tree */
4912 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4913 goto error;
4914 }
4915
Radek Krejci1d82ef62015-08-07 14:44:40 +02004916 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004917 if (strcmp(sub->ns->value, LY_NSYIN)) {
4918 /* extension */
4919 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004922 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004923 !strcmp(sub->name, "leaf-list") ||
4924 !strcmp(sub->name, "leaf") ||
4925 !strcmp(sub->name, "list") ||
4926 !strcmp(sub->name, "choice") ||
4927 !strcmp(sub->name, "uses") ||
4928 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004929 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02004930 !strcmp(sub->name, "action") ||
4931 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004932 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004933 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004934
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004935 /* array counters */
4936 } else if (!strcmp(sub->name, "typedef")) {
4937 c_tpdf++;
4938 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004939 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004940 goto error;
4941 }
4942 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004944 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4945 if (c_tpdf) {
4946 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004947 if (!grp->tpdf) {
4948 LOGMEM;
4949 goto error;
4950 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004951 }
Radek Krejcie534c132016-11-23 13:32:31 +01004952 if (c_ext) {
4953 grp->ext = calloc(c_ext, sizeof *grp->ext);
4954 if (!grp->ext) {
4955 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02004956 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004957 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004958 }
Radek Krejcie534c132016-11-23 13:32:31 +01004959 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4960 if (strcmp(sub->ns->value, LY_NSYIN)) {
4961 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01004962 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004963 retval->ext_size++;
4964 if (r) {
4965 goto error;
4966 }
4967 } else {
4968 /* typedef */
4969 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4970 grp->tpdf_size++;
4971 if (r) {
4972 goto error;
4973 }
4974 }
4975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004977 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004978 if (!root.child) {
4979 LOGWRN("Grouping \"%s\" without children.", retval->name);
4980 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004981 LY_TREE_FOR_SAFE(root.child, next, sub) {
4982 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004983 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004984 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004985 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004987 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004989 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004990 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004991 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004993 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004994 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004995 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004996 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004997 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004998 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004999 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005000 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005001 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005002 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005003 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005005 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 goto error;
5007 }
Radek Krejci73adb602015-07-02 18:07:40 +02005008
Michal Vasko345da0a2015-12-02 10:35:55 +01005009 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005012 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005013
5014error:
5015
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005016 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005018 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005022}
5023
Michal Vasko0d343d12015-08-24 14:57:36 +02005024/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005025static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005026read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005027 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005028{
Radek Krejcie0674f82015-06-15 13:58:51 +02005029 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005030 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005031 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005032 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005033 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005034 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005035
Radek Krejcie0674f82015-06-15 13:58:51 +02005036 /* init */
5037 memset(&root, 0, sizeof root);
5038
Michal Vasko38d01f72015-06-15 09:41:06 +02005039 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005040 if (!inout) {
5041 LOGMEM;
5042 return NULL;
5043 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005044 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005045
5046 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005047 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005048 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005049 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005050 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005051 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005052 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005053 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005054 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005055 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005056 }
5057
Radek Krejci76512572015-08-04 09:47:08 +02005058 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005059
Radek Krejci6ff885d2017-01-03 14:06:22 +01005060 if (read_yin_common(module, parent, retval, yin, OPT_MODULE)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02005061 goto error;
5062 }
5063
Radek Krejcia9544502015-08-14 08:24:29 +02005064 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5065
Radek Krejcic189a952016-07-11 15:27:07 +02005066 /* insert the node into the schema tree */
5067 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5068 goto error;
5069 }
5070
Michal Vasko38d01f72015-06-15 09:41:06 +02005071 /* data statements */
5072 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005073 if (strcmp(sub->ns->value, LY_NSYIN)) {
5074 /* extension */
5075 c_ext++;
5076 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005077 !strcmp(sub->name, "leaf-list") ||
5078 !strcmp(sub->name, "leaf") ||
5079 !strcmp(sub->name, "list") ||
5080 !strcmp(sub->name, "choice") ||
5081 !strcmp(sub->name, "uses") ||
5082 !strcmp(sub->name, "grouping") ||
5083 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005084 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005085 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005087 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005088 } else if (!strcmp(sub->name, "typedef")) {
5089 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005090
Radek Krejci1a31efe2016-07-29 11:04:16 +02005091 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005092 c_must++;
5093
Michal Vasko38d01f72015-06-15 09:41:06 +02005094 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005095 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005096 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005097 }
5098 }
5099
5100 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5101 if (c_tpdf) {
5102 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005103 if (!inout->tpdf) {
5104 LOGMEM;
5105 goto error;
5106 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005107 }
Radek Krejci19332802016-07-29 10:39:46 +02005108 if (c_must) {
5109 inout->must = calloc(c_must, sizeof *inout->must);
5110 if (!inout->must) {
5111 LOGMEM;
5112 goto error;
5113 }
5114 }
Radek Krejcie534c132016-11-23 13:32:31 +01005115 if (c_ext) {
5116 inout->ext = calloc(c_ext, sizeof *inout->ext);
5117 if (!inout->ext) {
5118 LOGMEM;
5119 goto error;
5120 }
5121 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005122
Radek Krejcie534c132016-11-23 13:32:31 +01005123 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5124 if (strcmp(sub->ns->value, LY_NSYIN)) {
5125 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01005126 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005127 retval->ext_size++;
5128 if (r) {
5129 goto error;
5130 }
5131 } else if (!strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005132 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
5133 inout->must_size++;
5134 if (r) {
5135 goto error;
5136 }
5137 } else { /* typedef */
5138 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5139 inout->tpdf_size++;
5140 if (r) {
5141 goto error;
5142 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005143 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005144 }
5145
5146 /* last part - process data nodes */
5147 LY_TREE_FOR_SAFE(root.child, next, sub) {
5148 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005149 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005150 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005151 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005152 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005153 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005154 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005155 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005156 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005157 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005158 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005159 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005160 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005161 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005162 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005163 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005164 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005165 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005166 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005167 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005168 goto error;
5169 }
Radek Krejci73adb602015-07-02 18:07:40 +02005170
Michal Vasko345da0a2015-12-02 10:35:55 +01005171 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005172 }
5173
Michal Vasko508a50d2016-09-07 14:50:33 +02005174 /* check XPath dependencies */
5175 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5176 goto error;
5177 }
5178
Michal Vasko38d01f72015-06-15 09:41:06 +02005179 return retval;
5180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005182
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005183 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005184 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005185 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005186 }
5187
5188 return NULL;
5189}
5190
Michal Vasko0d343d12015-08-24 14:57:36 +02005191/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005192static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005193read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005194 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005195{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005196 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005197 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005198 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005199 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005200 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005201 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02005202
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005203 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005204 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005205 return NULL;
5206 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005207
Michal Vaskoc6551b32015-06-16 10:51:43 +02005208 memset(&root, 0, sizeof root);
5209
Michal Vasko0ea41032015-06-16 08:53:55 +02005210 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005211 if (!notif) {
5212 LOGMEM;
5213 return NULL;
5214 }
Radek Krejci76512572015-08-04 09:47:08 +02005215 notif->nodetype = LYS_NOTIF;
5216 notif->prev = (struct lys_node *)notif;
5217 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005218
Radek Krejci6ff885d2017-01-03 14:06:22 +01005219 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005220 goto error;
5221 }
5222
Radek Krejcia9544502015-08-14 08:24:29 +02005223 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5224
Radek Krejcic189a952016-07-11 15:27:07 +02005225 /* insert the node into the schema tree */
5226 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5227 goto error;
5228 }
5229
Michal Vasko0ea41032015-06-16 08:53:55 +02005230 /* process rpc's specific children */
5231 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005232 if (strcmp(sub->ns->value, LY_NSYIN)) {
5233 /* extension */
5234 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005235 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005236
Michal Vasko0ea41032015-06-16 08:53:55 +02005237 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005238 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005239 !strcmp(sub->name, "leaf-list") ||
5240 !strcmp(sub->name, "leaf") ||
5241 !strcmp(sub->name, "list") ||
5242 !strcmp(sub->name, "choice") ||
5243 !strcmp(sub->name, "uses") ||
5244 !strcmp(sub->name, "grouping") ||
5245 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005246 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005247 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005250 } else if (!strcmp(sub->name, "typedef")) {
5251 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005252 } else if (!strcmp(sub->name, "if-feature")) {
5253 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005254 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005255 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005256 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005257 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005258 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005259 }
5260 }
5261
5262 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5263 if (c_tpdf) {
5264 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005265 if (!notif->tpdf) {
5266 LOGMEM;
5267 goto error;
5268 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005269 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005270 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005271 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5272 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005273 LOGMEM;
5274 goto error;
5275 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005276 }
Radek Krejci19332802016-07-29 10:39:46 +02005277 if (c_must) {
5278 notif->must = calloc(c_must, sizeof *notif->must);
5279 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005280 LOGMEM;
5281 goto error;
5282 }
5283 }
Radek Krejcie534c132016-11-23 13:32:31 +01005284 if (c_ext) {
5285 notif->ext = calloc(c_ext, sizeof *notif->ext);
5286 if (!notif->ext) {
5287 LOGMEM;
5288 goto error;
5289 }
5290 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005291
Radek Krejcie534c132016-11-23 13:32:31 +01005292 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5293 if (strcmp(sub->ns->value, LY_NSYIN)) {
5294 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01005295 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005296 retval->ext_size++;
5297 if (r) {
5298 goto error;
5299 }
5300 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005301 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5302 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005303 if (r) {
5304 goto error;
5305 }
Radek Krejci96299152016-06-22 10:17:50 +02005306 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005307 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005308 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005309 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005310 goto error;
5311 }
Radek Krejci19332802016-07-29 10:39:46 +02005312 } else if (!strcmp(sub->name, "must")) {
5313 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
5314 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005315 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005316 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005317 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005318 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005319 }
5320
5321 /* last part - process data nodes */
5322 LY_TREE_FOR_SAFE(root.child, next, sub) {
5323 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005324 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005325 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005326 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005327 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005328 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005329 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005330 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005331 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005332 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005333 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005334 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005335 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005336 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005337 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005338 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005339 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005340 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005341 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005342 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005343 goto error;
5344 }
Radek Krejci73adb602015-07-02 18:07:40 +02005345
Michal Vasko345da0a2015-12-02 10:35:55 +01005346 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005347 }
5348
Michal Vasko508a50d2016-09-07 14:50:33 +02005349 /* check XPath dependencies */
5350 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5351 goto error;
5352 }
5353
Michal Vasko0ea41032015-06-16 08:53:55 +02005354 return retval;
5355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005356error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005357
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005358 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005359 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005360 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005361 }
5362
5363 return NULL;
5364}
5365
Michal Vasko0d343d12015-08-24 14:57:36 +02005366/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005367static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005368read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005369 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005370{
Radek Krejcie0674f82015-06-15 13:58:51 +02005371 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005372 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005373 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005374 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005375 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005376 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005377
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005378 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005379 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005380 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005381 return NULL;
5382 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005383 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005384 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005385 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005386 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005387 return NULL;
5388 }
5389 }
5390 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005391
Radek Krejcie0674f82015-06-15 13:58:51 +02005392 /* init */
5393 memset(&root, 0, sizeof root);
5394
Michal Vasko38d01f72015-06-15 09:41:06 +02005395 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005396 if (!rpc) {
5397 LOGMEM;
5398 return NULL;
5399 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005400 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005401 rpc->prev = (struct lys_node *)rpc;
5402 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005403
Radek Krejci6ff885d2017-01-03 14:06:22 +01005404 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005405 goto error;
5406 }
5407
Radek Krejcia9544502015-08-14 08:24:29 +02005408 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5409
Radek Krejcic189a952016-07-11 15:27:07 +02005410 /* insert the node into the schema tree */
5411 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5412 goto error;
5413 }
5414
Michal Vasko38d01f72015-06-15 09:41:06 +02005415 /* process rpc's specific children */
5416 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005417 if (strcmp(sub->ns->value, LY_NSYIN)) {
5418 /* extension */
5419 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005420 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005421 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005422 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005423 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005424 goto error;
5425 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005426 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005427 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005428 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005429 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005430 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005431 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005432 goto error;
5433 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005434 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005435 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005436 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005438 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005439 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005440 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005441 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005444 } else if (!strcmp(sub->name, "typedef")) {
5445 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005446 } else if (!strcmp(sub->name, "if-feature")) {
5447 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005448 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005449 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005450 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005451 }
5452 }
5453
5454 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5455 if (c_tpdf) {
5456 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005457 if (!rpc->tpdf) {
5458 LOGMEM;
5459 goto error;
5460 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005461 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005462 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005463 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5464 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005465 LOGMEM;
5466 goto error;
5467 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005468 }
Radek Krejcie534c132016-11-23 13:32:31 +01005469 if (c_ext) {
5470 rpc->ext = calloc(c_ext, sizeof *rpc->ext);
5471 if (!rpc->ext) {
5472 LOGMEM;
5473 goto error;
5474 }
5475 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005476
Radek Krejcie534c132016-11-23 13:32:31 +01005477 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5478 if (strcmp(sub->ns->value, LY_NSYIN)) {
5479 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01005480 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005481 retval->ext_size++;
5482 if (r) {
5483 goto error;
5484 }
5485 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005486 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5487 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005488 if (r) {
5489 goto error;
5490 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005491 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005492 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005493 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005494 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005495 goto error;
5496 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005497 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005498 }
5499
5500 /* last part - process data nodes */
5501 LY_TREE_FOR_SAFE(root.child, next, sub) {
5502 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005503 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005504 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005505 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005506 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005507 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005508 goto error;
5509 }
Radek Krejci73adb602015-07-02 18:07:40 +02005510
Michal Vasko345da0a2015-12-02 10:35:55 +01005511 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005512 }
5513
Michal Vasko38d01f72015-06-15 09:41:06 +02005514 return retval;
5515
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005516error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005517
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005518 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005519 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005520 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005521 }
5522
5523 return NULL;
5524}
5525
Michal Vasko0d343d12015-08-24 14:57:36 +02005526/* logs directly
5527 *
Radek Krejci74705112015-06-05 10:25:44 +02005528 * resolve - referenced grouping should be bounded to the namespace (resolved)
5529 * only when uses does not appear in grouping. In a case of grouping's uses,
5530 * we just get information but we do not apply augment or refine to it.
5531 */
Radek Krejci76512572015-08-04 09:47:08 +02005532static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005533read_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 +02005534{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005535 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005536 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005537 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005538 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01005539 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005540 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005542 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005543 if (!uses) {
5544 LOGMEM;
5545 return NULL;
5546 }
Radek Krejci76512572015-08-04 09:47:08 +02005547 uses->nodetype = LYS_USES;
5548 uses->prev = (struct lys_node *)uses;
5549 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005550
Radek Krejcia9544502015-08-14 08:24:29 +02005551 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005552 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005553
Radek Krejci6ff885d2017-01-03 14:06:22 +01005554 if (read_yin_common(module, parent, retval, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005555 goto error;
5556 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005557
Radek Krejcia9544502015-08-14 08:24:29 +02005558 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5559
Radek Krejcic189a952016-07-11 15:27:07 +02005560 /* insert the node into the schema tree */
5561 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5562 goto error;
5563 }
5564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005565 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005566 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005567 if (strcmp(sub->ns->value, LY_NSYIN)) {
5568 /* extension */
5569 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005570 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005571 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005572 c_ref++;
5573 } else if (!strcmp(sub->name, "augment")) {
5574 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005575 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005576 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005577 } else if (!strcmp(sub->name, "when")) {
5578 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005579 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005580 goto error;
5581 }
5582
5583 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005584 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005585 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005586 goto error;
5587 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005588 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005589 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005590 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005591 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005592 }
5593 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005595 /* process properties with cardinality 0..n */
5596 if (c_ref) {
5597 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005598 if (!uses->refine) {
5599 LOGMEM;
5600 goto error;
5601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005602 }
5603 if (c_aug) {
5604 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005605 if (!uses->augment) {
5606 LOGMEM;
5607 goto error;
5608 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005609 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005610 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005611 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5612 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005613 LOGMEM;
5614 goto error;
5615 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005616 }
Radek Krejcie534c132016-11-23 13:32:31 +01005617 if (c_ext) {
5618 uses->ext = calloc(c_ext, sizeof *uses->ext);
5619 if (!uses->ext) {
5620 LOGMEM;
5621 goto error;
5622 }
5623 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005624
Radek Krejcie534c132016-11-23 13:32:31 +01005625 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5626 if (strcmp(sub->ns->value, LY_NSYIN)) {
5627 /* extension */
Radek Krejci0aa821a2016-12-08 11:21:35 +01005628 r = fill_yin_ext(retval, LYEXT_PAR_NODE, module, sub, &retval->ext[retval->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005629 retval->ext_size++;
5630 if (r) {
5631 goto error;
5632 }
5633 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005634 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005635 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005636 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005637 goto error;
5638 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005639 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005640 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5641 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005642 if (r) {
5643 goto error;
5644 }
5645 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005646 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005647 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005648 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005649 goto error;
5650 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005651 }
5652 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005653
Radek Krejci48464ed2016-03-17 15:44:09 +01005654 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005655 goto error;
5656 }
Radek Krejci74705112015-06-05 10:25:44 +02005657
Michal Vasko508a50d2016-09-07 14:50:33 +02005658 /* check XPath dependencies */
5659 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5660 goto error;
5661 }
5662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005663 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005664
5665error:
5666
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005667 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005670}
5671
Michal Vasko0d343d12015-08-24 14:57:36 +02005672/* logs directly
5673 *
5674 * common code for yin_read_module() and yin_read_submodule()
5675 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005676static int
Radek Krejcic071c542016-01-27 14:57:51 +01005677read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5678 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005679{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005680 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01005681 struct lyxml_elem *next, *child, *child2, root, grps, augs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005682 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005683 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005684 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005685 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005686 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005687 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005688 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005689 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01005690 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;
5691 int c_ext = 0, c_extinst = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005692
Radek Krejcic071c542016-01-27 14:57:51 +01005693 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005694 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005696 /* init */
5697 memset(&root, 0, sizeof root);
5698 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005699 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01005700 memset(&exts, 0, sizeof exts);
Radek Krejcie0674f82015-06-15 13:58:51 +02005701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 /*
5703 * in the first run, we process elements with cardinality of 1 or 0..1 and
5704 * count elements with cardinality 0..n. Data elements (choices, containers,
5705 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5706 * need have all top-level and groupings already prepared at that time. In
5707 * the middle loop, we process other elements with carinality of 0..n since
5708 * we need to allocate arrays to store them.
5709 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005710 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01005711 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005712 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005713 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005714 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005715 } else if (strcmp(child->ns->value, LY_NSYIN)) {
5716 /* possible extension instance */
5717 lyxml_unlink_elem(module->ctx, child, 2);
5718 lyxml_add_child(module->ctx, &exts, child);
5719 c_extinst++;
5720 } else if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005721 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005722 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005723 goto error;
5724 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005725 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005726 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005727 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005728 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005730 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005731 goto error;
5732 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005733 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005734 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005735 goto error;
5736 }
5737 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005738 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005739 } else if (submodule && !strcmp(child->name, "belongs-to")) {
5740 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005741 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005742 goto error;
5743 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005744 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005745 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005746 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005747 goto error;
5748 }
Radek Krejcif3886932015-06-04 17:36:06 +02005749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005750 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005751 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005752 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005753 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005754 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005755 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005756 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005757 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005758 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005759 goto error;
5760 }
5761 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005762 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005763 /* check here differs from a generic prefix check, since this prefix
5764 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005765 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005766 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005767 goto error;
5768 }
Radek Krejcic071c542016-01-27 14:57:51 +01005769 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005771 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005772 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005773
5774 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005775 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005776 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005777 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005778 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005779 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005780 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005781 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005782 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005783 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005784 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005785 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005786 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005787 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005788 lyxml_unlink_elem(ctx, child, 2);
5789 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005790
Radek Krejci1d82ef62015-08-07 14:44:40 +02005791 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005792 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005794 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005795 } else if (!strcmp(child->name, "container") ||
5796 !strcmp(child->name, "leaf-list") ||
5797 !strcmp(child->name, "leaf") ||
5798 !strcmp(child->name, "list") ||
5799 !strcmp(child->name, "choice") ||
5800 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005801 !strcmp(child->name, "anyxml") ||
5802 !strcmp(child->name, "rpc") ||
5803 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005804 lyxml_unlink_elem(ctx, child, 2);
5805 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005806
Radek Krejci1d82ef62015-08-07 14:44:40 +02005807 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005808 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005809 lyxml_unlink_elem(ctx, child, 2);
5810 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005812 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005813 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005814 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005815 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005816 goto error;
5817 }
Radek Krejcic071c542016-01-27 14:57:51 +01005818 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005819 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005820 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005821 goto error;
5822 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005823 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005824 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005825 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005826 goto error;
5827 }
Radek Krejcic071c542016-01-27 14:57:51 +01005828 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005829 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005830 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005831 goto error;
5832 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005833 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005834 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005835 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005836 goto error;
5837 }
Radek Krejcic071c542016-01-27 14:57:51 +01005838 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005839 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005840 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005841 goto error;
5842 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005843 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005844 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005845 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005846 goto error;
5847 }
Radek Krejcic071c542016-01-27 14:57:51 +01005848 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005849 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005850 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005851 goto error;
5852 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005853 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005854 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005855 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005856 goto error;
5857 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005858 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005859 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005860 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005861 goto error;
5862 }
Radek Krejcic071c542016-01-27 14:57:51 +01005863 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005864 if (!strcmp(value, "1")) {
5865 if (submodule) {
5866 if (module->version > 1) {
5867 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5868 goto error;
5869 }
5870 } else {
5871 module->version = 1;
5872 }
5873 } else {
5874 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005875 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005876 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5877 goto error;
5878 }
5879 } else {
5880 module->version = 2;
5881 }
5882 }
5883
Michal Vasko345da0a2015-12-02 10:35:55 +01005884 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005885
Radek Krejci1d82ef62015-08-07 14:44:40 +02005886 } else if (!strcmp(child->name, "extension")) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09005887 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02005888
Radek Krejcia1a6b762016-11-14 09:53:38 +09005889 } else if (!strcmp(child->name, "deviation")) {
5890 c_dev++;
5891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005892 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005893 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005894 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005895 }
5896 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005897
Radek Krejcic071c542016-01-27 14:57:51 +01005898 /* check for mandatory statements */
5899 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005900 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005901 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005902 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005903 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005904 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005905 goto error;
5906 }
5907 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005908 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005909 goto error;
5910 }
5911 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005913 /* allocate arrays for elements with cardinality of 0..n */
5914 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005915 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5916 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005917 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005918 LOGMEM;
5919 goto error;
5920 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005921 /* set stop block for possible realloc */
5922 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005923 }
5924 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005925 trg->rev = calloc(c_rev, sizeof *trg->rev);
5926 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005927 LOGMEM;
5928 goto error;
5929 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005930 }
5931 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005932 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5933 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005934 LOGMEM;
5935 goto error;
5936 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005937 }
5938 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005939 trg->ident = calloc(c_ident, sizeof *trg->ident);
5940 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005941 LOGMEM;
5942 goto error;
5943 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005944 }
5945 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005946 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5947 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005948 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005949 LOGMEM;
5950 goto error;
5951 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005952 /* set stop block for possible realloc */
5953 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005954 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005955 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005956 trg->augment = calloc(c_aug, sizeof *trg->augment);
5957 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005958 LOGMEM;
5959 goto error;
5960 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005961 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005962 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005963 trg->features = calloc(c_ftrs, sizeof *trg->features);
5964 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005965 LOGMEM;
5966 goto error;
5967 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005968 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005969 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005970 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5971 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005972 LOGMEM;
5973 goto error;
5974 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005975 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09005976 if (c_ext) {
5977 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
5978 if (!trg->extensions) {
5979 LOGMEM;
5980 goto error;
5981 }
5982 }
Radek Krejcie534c132016-11-23 13:32:31 +01005983 if (c_extinst) {
5984 trg->ext = calloc(c_extinst, sizeof *trg->ext);
5985 if (!trg->ext) {
5986 LOGMEM;
5987 goto error;
5988 }
5989 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005990
Michal Vasko2f7925f2015-10-21 15:06:56 +02005991 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5992 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005993 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01005994 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01005995 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005996 if (r) {
5997 goto error;
5998 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005999
Radek Krejci1d82ef62015-08-07 14:44:40 +02006000 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006001 memset(&inc, 0, sizeof inc);
6002 /* 1) pass module, not trg, since we want to pass the main module
6003 * 2) we cannot pass directly the structure in the array since
6004 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01006005 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02006006 if (!r) {
6007 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02006008 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
6009 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02006010 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006011 goto error;
6012 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006013
Radek Krejci1d82ef62015-08-07 14:44:40 +02006014 } else if (!strcmp(child->name, "revision")) {
6015 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01006016 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006017 goto error;
6018 }
Radek Krejcic071c542016-01-27 14:57:51 +01006019 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006020 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01006021 for (i = 0; i < trg->rev_size; i++) {
6022 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006023 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
6024 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006025 }
6026 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006027
Radek Krejci1d82ef62015-08-07 14:44:40 +02006028 LY_TREE_FOR(child->child, child2) {
6029 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006030 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006031 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006032 goto error;
6033 }
Radek Krejcic071c542016-01-27 14:57:51 +01006034 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
6035 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006036 goto error;
6037 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006038 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006039 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006040 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006041 goto error;
6042 }
Radek Krejcic071c542016-01-27 14:57:51 +01006043 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
6044 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006045 goto error;
6046 }
6047 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006048 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006049 goto error;
6050 }
6051 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006053 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01006054 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006055 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01006056 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01006057 if (!value) {
6058 LOGMEM;
6059 goto error;
6060 }
Radek Krejcic071c542016-01-27 14:57:51 +01006061 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
6062 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006063 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02006064
Radek Krejci749190d2016-02-18 16:26:25 +01006065 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01006066 value = trg->rev[0].dsc;
6067 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
6068 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006069 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006070
Radek Krejci749190d2016-02-18 16:26:25 +01006071 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01006072 value = trg->rev[0].ref;
6073 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
6074 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006075 }
6076 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006077
Radek Krejcic071c542016-01-27 14:57:51 +01006078 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006079
Radek Krejci1d82ef62015-08-07 14:44:40 +02006080 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006081 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6082 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006083 if (r) {
6084 goto error;
6085 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006086
Radek Krejci1d82ef62015-08-07 14:44:40 +02006087 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006088 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6089 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006090 if (r) {
6091 goto error;
6092 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006093
Radek Krejci1d82ef62015-08-07 14:44:40 +02006094 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006095 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6096 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006097 if (r) {
6098 goto error;
6099 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006100
Radek Krejcia1a6b762016-11-14 09:53:38 +09006101 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006102 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006103 trg->extensions_size++;
6104 if (r) {
6105 goto error;
6106 }
6107
Radek Krejci1d82ef62015-08-07 14:44:40 +02006108 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006109 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6110 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006111 if (r) {
6112 goto error;
6113 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006114 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006115 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006116
Radek Krejcib8f98c12016-06-24 10:30:46 +02006117 if (!submodule) {
6118 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02006119 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02006120 if (module->inc_size) {
6121 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
6122 if (!module->inc) {
6123 LOGMEM;
6124 goto error;
6125 }
6126 }
6127 if (module->imp_size) {
6128 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
6129 if (!module->imp) {
6130 LOGMEM;
6131 goto error;
6132 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02006133 }
6134 }
Radek Krejcic071c542016-01-27 14:57:51 +01006135
Radek Krejcie534c132016-11-23 13:32:31 +01006136 /* process extension instances */
6137 LY_TREE_FOR_SAFE(exts.child, next, child) {
Radek Krejci0aa821a2016-12-08 11:21:35 +01006138 r = fill_yin_ext(trg, LYEXT_PAR_MODULE, module, child, &trg->ext[trg->ext_size], unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006139 trg->ext_size++;
6140 if (r) {
6141 goto error;
6142 }
6143 }
6144
6145
Radek Krejcif5be10f2015-06-16 13:29:36 +02006146 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006147 * refer to them. Submodule's data nodes are stored in the
6148 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006149 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006150 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006151 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006152 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006153 goto error;
6154 }
Radek Krejci74705112015-06-05 10:25:44 +02006155
Michal Vasko345da0a2015-12-02 10:35:55 +01006156 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006157 }
Radek Krejci74705112015-06-05 10:25:44 +02006158
Radek Krejcif5be10f2015-06-16 13:29:36 +02006159 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006160 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006161
Radek Krejci1d82ef62015-08-07 14:44:40 +02006162 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006163 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006164 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006165 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006166 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006167 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006168 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006169 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006170 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006171 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006172 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006173 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006174 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02006175 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
6176 } else if (!strcmp(child->name, "anydata")) {
6177 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006178 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006179 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006180 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006181 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006182 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006183 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006184 goto error;
6185 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006186
Michal Vasko345da0a2015-12-02 10:35:55 +01006187 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006188 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006189
Michal Vasko2f7925f2015-10-21 15:06:56 +02006190 /* ... and finally augments (last, so we can augment our data, for instance) */
6191 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01006192 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
6193 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006194
Michal Vasko2f7925f2015-10-21 15:06:56 +02006195 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006196 goto error;
6197 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006198 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006199 }
6200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006201 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02006202
6203error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006204 /* cleanup */
6205 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006206 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006207 }
6208 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006209 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006210 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006211 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006212 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006213 }
Radek Krejcie534c132016-11-23 13:32:31 +01006214 while (exts.child) {
6215 lyxml_free(module->ctx, exts.child);
6216 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006218 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02006219}
6220
Michal Vasko0d343d12015-08-24 14:57:36 +02006221/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006222struct lys_submodule *
6223yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02006224{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006225 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006226 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006227 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006228
Michal Vasko5a721fd2016-02-16 12:16:48 +01006229 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006230
Radek Krejci722b0072016-02-01 17:09:45 +01006231 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006232 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01006233 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006234 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006236 /* check root element */
6237 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006238 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006239 goto error;
6240 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006242 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006243 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006244 goto error;
6245 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006246
Michal Vasko5a721fd2016-02-16 12:16:48 +01006247 submodule = calloc(1, sizeof *submodule);
6248 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006249 LOGMEM;
6250 goto error;
6251 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006252
Michal Vasko5a721fd2016-02-16 12:16:48 +01006253 submodule->ctx = module->ctx;
6254 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
6255 submodule->type = 1;
6256 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02006257
Michal Vasko5a721fd2016-02-16 12:16:48 +01006258 LOGVRB("Reading submodule \"%s\".", submodule->name);
6259 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006260 goto error;
6261 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006263 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01006264 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02006265
Michal Vasko5a721fd2016-02-16 12:16:48 +01006266 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006267 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02006268
6269error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006270 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006271 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01006272 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01006273
Michal Vasko5a721fd2016-02-16 12:16:48 +01006274 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01006275 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01006276 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01006277 }
6278
Michal Vasko5a721fd2016-02-16 12:16:48 +01006279 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01006280
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006281 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6282 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006283 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006284 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006285}
6286
Michal Vasko0d343d12015-08-24 14:57:36 +02006287/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006288struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01006289yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006290{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006291 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006292 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006293 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006294 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006295
Radek Krejcic071c542016-01-27 14:57:51 +01006296 unres = calloc(1, sizeof *unres);
6297 if (!unres) {
6298 LOGMEM;
6299 return NULL;
6300 }
6301
Radek Krejci722b0072016-02-01 17:09:45 +01006302 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006303 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01006304 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006305 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006307 /* check root element */
6308 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02006309 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006310 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
6311 } else {
6312 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02006313 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006314 goto error;
6315 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006317 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006318 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006319 goto error;
6320 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006322 module = calloc(1, sizeof *module);
6323 if (!module) {
6324 LOGMEM;
6325 goto error;
6326 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006328 module->ctx = ctx;
6329 module->name = lydict_insert(ctx, value, strlen(value));
6330 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02006331 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02006332
Michal Vasko9f258e42016-02-11 11:36:27 +01006333 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01006334 if (read_sub_module(module, NULL, yin, unres)) {
6335 goto error;
6336 }
6337
6338 /* resolve rest of unres items */
6339 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006340 goto error;
6341 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006342
Radek Krejciff4874d2016-03-07 12:30:50 +01006343 if (revision) {
6344 /* check revision of the parsed model */
6345 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01006346 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
6347 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01006348 goto error;
6349 }
6350 }
6351
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006352 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006353 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006354 }
Radek Krejci63a91a92015-07-29 13:31:04 +02006355
Radek Krejci27fe55e2016-09-13 17:13:35 +02006356 if (module->deviation_size && !module->implemented) {
6357 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
6358 /* deviations always causes target to be made implemented,
6359 * but augents and leafrefs not, so we have to apply them now */
6360 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02006361 goto error;
6362 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006363 }
6364
Michal Vasko345da0a2015-12-02 10:35:55 +01006365 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01006366 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01006367 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006368 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006369
6370error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006371 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01006372 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01006373 unres_schema_free(module, &unres);
6374
6375 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006376 if (ly_vecode != LYVE_SUBMODULE) {
6377 LOGERR(ly_errno, "Module parsing failed.");
6378 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01006379 return NULL;
6380 }
6381
6382 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006383
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006384 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01006385 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006386 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006387}